-
For those of you who may think WPF is too slow, you gotta check this out. Visual Studio 2010's new WPF-based code editor is lightening fast, especially when compared over a fast FiOS Remote Desktop connection to gVim!
-
User Account Control, the feature in Vista that causes installers and some applications to require "elevation" to administrator privileges to run, cuts both ways. It's designed to protect users from apps that try to make system-level changes by giving the user the heads up that it's about to happen and gives the user the chance to abort the operation. The flip-side is that since this is an inconvenience to users, software writers are motivated to write their software so that it doesn't require admin privileges, further improving security on the system.
While there are problems with UAC, the most aggravating (for me) is that Vista insists on elevating some apps that don't need elevation. For example, all setup.exe programs always elevate, since most users don't want setup programs failing halfway through. Other programs, like regedit.exe, have manifests that say to Vista, in effect, "I can run in user mode or admin mode, but give me admin mode if it's available". So when a non-admin account launches regedit.exe, regedit comes up without requesting elevation. But if an admin account launches regedit, the UAC dialog comes up. Fair enough.
But what if I don't want to elevate an app that wants it? For example, if I didn't want regedit.exe to have admin privileges to help protect me from myself when I only intended to modify HKEY_CURRENT_USER, which doesn't require admin rights.
But the more common scenario I find myself in is when I download software I do not entirely trust. The software comes with a setup program, which I have to run in order to use the software. I intend to install the program in a private user area rather than Program Files in order to avoid having to elevate the program or its setup program. But Vista always insists on elevating setup.exe programs.
There is a way to coerce Vista to not elevate a process that it otherwise would.
REM The next command MUST be run from an elevated command window.
REM It launches regedit.exe WITHOUT elevated privileges.
runas /trustlevel:0x20000 regedit.exe
Ironically, starting a program explicitly without elevation requires an elevated command prompt. Go figure.
So next time an untrusted program prompts for elevation that you don't want to give, try this nifty command.
-
The GZip encoder is not included in NetCF as it is on the desktop WCF, but it isn't hard to build yourself and in fact we have released a sample of exactly how to add your own GZip encoder to NetCF:
http://go.microsoft.com/fwlink/?LinkId=108652
So many people have asked me for it lately I thought I'd better just post the link. Have fun!
-
Some humorous pros and cons to Visual Studio, if the Microsoft Office team were ever to take over. (disclaimer: this is a tongue in cheek post. No offense -- only laughs intended)
- Visual Studio 2008 would be able to load VC7 projects, modify them in any way VC7 allowed, and save the project back to VC7 format, allowing you to work with others still using VC7.
- You could download an extension to VC7 that would allow you to work with VS2008 projects in a limited way.
- Your projects would open in any copy of Visual Studio just fine, until you added any code to it. Then VS would refuse to load it until you changed the security settings in Tools -> Options from High to Low. And you'd still get a security warning at every load.
- To send your codebase to someone else without allowing them to change it, you would Save to PDF.
- Source control would be integrated into each individual source file (but you'd have to turn it on first, per file), and merging changes from others would involve Track Changes with
strikethroughs and underlines instead of yellows and reds. - Source files would become programmable with embedded macro scripts, allowing a change in one part of the source file to affect other areas, perhaps with some intermediate calculation.
- Compilation would occur in the background, or instantaneously on demand.
- No build breaks. Ever. But the spell checker might point out some possible areas of improvement.
- Methods would be phrases and have spaces.
- Shakespeare would be the default programming language.
-
You know that Find text box in the toolbar of Visual Studio? Those of us who are keyboard-inclined probably never use it because Ctrl+F is quicker than moving your hand to the mouse. But there is a hidden gem of a feature inside it that really makes me feel like a power user that I wanted to share.
That find box doubles as a Command Window prompt if you just start with a '>' sign. The feature in this that I use the most is this:
First jump up to that box using the keystroke Ctrl+/. Now type ">of " and follow with the start of a filename. As fast as you can type, Visual Studio searches your entire solution for a file or path that starts with the characters you type and you can quickly select that file (with the keyboard using the arrow keys if you wish) and open it. If you're working in a solution with several projects or folders, this can be a significant time saver.
For those of you unfamiliar with the Command Window, you can think of it like an Immediate Window that you use with the debugger, except that instead of controlling the debuggee, you're controlling Visual Studio. It's like the VS macro editor, except that everything you type takes immediate effect. To have this conveniently just a Ctrl+/, > keystroke away, especially when ">of " (short for Open File) is such a convenient acronym to search across your entire solution is awesome.
-
If you are a web developer I hope you've considered accepting OpenID credentials for logging in your users. If you have an ASP.NET web site, the process of adding OpenID support to your web site couldn't be easier when you use the free C# DotNetOpenId library.
Supporting OpenID is a great idea:
- No more "I forgot my username/password" pages.
- No more "Change Password" pages.
- Your users have one less username/password to make-up/reuse when they join your site.
- Users who prefer greater security than a username/password provides can choose an OpenID Provider that provides that assurance, without you having to enhance your site.
- It's free. And so are the libraries that you can drop in to add support for it.
-
In C++, TCHAR, LPCTSTR, CString, and other types discretely change to their char/WCHAR, CStringA/CStringW counterparts depending on whether UNICODE is defined in your source code. Cool. By conscientiously using _countof(x) instead of sizeof(x) where appropriate and TCHAR's everywhere instead of char/WCHAR, you can write code that will compile with ANSI or UNICODE support as easy as flipping a switch. But these tricks are not safe in .h header files.
Consider the following very simple scenario:
tool.h:
void SayHello(CString recipient);
tool.cpp
//#define UNICODE
#include "tool.h"
void SayHello(CString recipient)
{
printf(_T("Hello, %s"), recipient);
}
Compiled into a standalone app, these two files would easily compile with or without the UNICODE symbol set and the right thing would happen.
But now consider that you compiled this not into a standalone .exe but into a .lib or .dll, and shared out the .h header file with some consuming application (which might be an external customer). That header file will be #include'd into their app, which may or may not define the UNICODE symbol. Suppose you defined UNICODE and the linking app did not. The header file will automatically adjust to the consuming app's ANSI style strings and the C++ compiler and linker will be perfectly happy. You won't know there's a problem with the app passing ANSI strings to your UNICODE library until runtime when you get random data corruption and application crashes.
How do you avoid this? Well there are two ways, really. If you already have an extensive library written with header files that use TCHARs and their cousins, just compile and ship both a UNICODE and an ANSI version of your library (toolA.lib and toolU.lib). Then instruct your customer to link to the correct one.
But if you're writing a library from scratch, consider using all strongly-typed ANSI or UNICODE character types in your .h files, and in the method signatures of your .CPP files. Then use whatever generic TCHAR's make sense within the implementation of your methods. So for example:
tool.h:
void SayHello(CStringW recipient);
tool.cpp
//#define UNICODE
#include "tool.h"
void SayHello(CStringW recipient)
{
USES_CONVERSION;
wprintf(L"Hello, %s", recipient);
// Call some ATL/MFC function that is only available in TCHARs
TCHAR szBuffer[] = _T("Some TCHAR buffer");
SomeImplementationSpecificMethod(szBuffer, CW2T(recipient));
}
This will compile with or without the UNICODE symbol defined, but the method signature will always be UNICODE, and the internals of method implementation will automatically adjust as appropriate for UNICODE or ANSI support.
-
Writing Visual Studio add-ins gives you the power to do some impressive things within the IDE to enhance your productivity. Unfortunately getting your add-in to load into Visual Studio can sometimes be a pain. Here's just a tip you should know about the .AddIn file that Visual Studio generates for you.
The path you provide to the add-in assembly .dll should be relative to the location of the .AddIn file itself. Absolute paths do not work. If you try using one, you get an unhelpful error dialog that mentions error code 0x80004005.
Hopefully we can get some more useful error messages in future versions of Visual Studio.
-
Well this is my first post as a member of the Visual Studio Platform & Ecosystem team. My second full day on the job, and I've found some less-than-ideal areas of Visual Studio that I'm eager to improve for myself and for you, our customers. How exciting. I'll do my best to post to my blog whenever I run across some unexpected scenario that is likely to hit customers and how to work around it.
So on to the first scenario...
Scenario
You have Visual Studio 2008 installed, but some Visual Studio Solution files (.sln) don't open when you double-click on them. In fact, nothing happens.
Analysis
When you double-click on a .sln file, a small program called vslauncher.exe is called with the path to your .sln file as its first argument. The job of vslauncher.exe is to read enough of your .sln file to determine which version of Visual Studio to use to open your file. Since you may have several versions of Visual Studio installed (VS2003, 2005, 2008, Express SKUs, etc.) you probably want to open the solution with the same copy of Visual Studio that you used to create it.
The issue comes up when your .sln file signature (the first two lines of your file) don't match any known release of Visual Studio. Visual Studio 2008 .sln files typically start with these two lines:
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
But suppose you have a .sln file that was created with a Visual Studio 2008 beta. You might have a .sln file that starts with this instead:
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio Codename Orcas When Visual Studio 2008 RTM reads this, it doesn't recognize its earlier beta versions' solution file signatures and just quits. It would be nice if a user-friendly message telling what happened would pop up. Alas, it does not.
Workaround
Simply open your .sln file in Notepad and change "Codename Orcas" to "2008" on the second line.
[Update 2/16/08] This blog was featured on Channel 9, and as a result a couple of people wrote up a PowerShell script and a C# program to automate updating all your .sln files at once. Very cool.
-
My first post in the provisioning series introduced what provisioning of your Windows Mobile device means and the basics of why you would want to do it. In future posts I'll give some concrete examples of XML that accomplish a few common tasks. But what good are XML examples if you can't try them out on your device or emulator? It would be much better if you had an app that would let you write in XML and see what happens when you send it to the provisioning API of Windows Mobile. I'd like to introduce you to a sample I wrote just for this purpose.
The open-source Windows Mobile Provisioning tool is a .NET Compact Framework application that exposes provisioning directly to the user. It will take strings of XML and pass them directly to Windows Mobile and return the resulting XML. It also has an interface to help you set a proxy server and add domains to the Work network and crafts the provisioning XML for you.
Over time I may add additional built-in provisioning scenarios to the sample. But for now, download it, compile it, and try it out. Let me know what you think, either here or on the Discussions page for this sample.
-
Microsoft recently launched the MSDN Code Gallery for Microsoft employees and others to share code and software using the Microsoft Public License. MSDN Code Gallery looks and feels very much like CodePlex, but Code Gallery lacks the TFS source control feature and developers can only publish their source code and binaries as releases.
As a Microsoft employee, I am happy to see this site launch as it finally gives us an easy way to publish more source code from our blogs. Watch my blog for a new device provisioning app that I will publish soon.
-
I have accepted a new position within Microsoft with the Visual Studio Platform & Ecosystem team. Rather than working on the .NET Compact Framework I will be working on "VS10".
I don't actually make the transition for a few more weeks, so I look forward to several more posts on NetCF topics before leaving.
-
The XmlSerializer found in the .NET Compact Framework has a very different implementation than the one found in the full .NET Framework. The reasons for the differences include size and performance constraints that make the desktop's XmlSerializer inappropriate for devices.
As a result of the different implementation, there are inevitably going to be differences between how each serializer turns objects into XML and back again. We try to minimize these differences so that your C# code will run on NetCF and desktop in a very portable way. When we find differences, we have to weigh the consequences of possibly breaking backward compatibility with applications written for earlier versions of NetCF against breaking compatibility with desktop for current and future applications.
One area where cross-platform compatibility becomes particularly important is in web services. When you generate web service proxies for your NetCF applications using Visual Studio's Add Web Reference function (or the command line wsdl.exe, xsd.exe, or NetCFSvcUtil.exe tools) you expect those proxies to serialize to XML that the service is expecting. These tools are generally developed and tested against the desktop's version of the XmlSerializer more thoroughly than against the NetCF XmlSerializer. So any differences in how NetCF's XmlSerializer works could cause incompatible xml to be sent to a service.
As I have been code reviewing .NET Compact Framework's version of the serializer and fixing bugs in it, I've come across a number of differences in how the two serializers behave that can affect web services. Some of these fixes made it into NetCF 2.0 SP2. Many more made it into NetCF 3.5. But quite a few issues were discovered too late to fix in the NetCF 3.5 release.
In an upcoming NetCF release there are likely to be some breaking changes to the way the XmlSerializer works in order to improve web service and desktop compatibility. This is likely to only affect applications that use multiple namespaces in a single type that is being serialized as that is where most of the bugs seem to be.
You can prepare for these changes by testing your application on the full .NET Framework today. If it runs correctly there, then it will probably run correctly on a future version of the .NET Compact Framework. If you notice that the XML the desktop produces is different than what NetCF produces, you will probably need to adjust your code so that it produces the desired XML on the full Framework, and consider releasing a service pack for your own application to your customers who are using new versions of NetCF.
A full list of breaking changes is published with each release of the .NET Compact Framework. You should review those if your NetCF app uses the XmlSerializer.
-
The Windows Communication Foundation introduced the new DataContractSerializer to replace the XmlSerializer in many scenarios. The DataContractSerializer is faster than the XmlSerializer, but has certain limitations. For example it does not support serializing an object's members as XML attributes. When you write a WCF client that calls a service, WCF will generate a proxy class that defaults to using the DataContractSerializer and falls back to the XmlSerializer if the service uses features that the DataContractSerializer does not support. This fallback mechanism is automatic if you're using WCF's service model.
But if you're working at WCF's messaging layer, you must explicitly choose which serializer to use. You can use any serializer that derives from System.Runtime.Serialization.XmlObjectSerializer. System.Runtime.Serialization.DataContractSerializer already derives from this class -- but System.Xml.Serialization.XmlSerializer does not. So you have some work to do before you can use the XmlSerializer as your serializer of choice at the messaging layer of WCF.
In order to use the XmlSerializer to send messages with WCF, we have to define a class that derives from XmlObjectSerializer and uses the XmlSerializer internally. In essence we will create a wrapper class for the XmlSerializer that makes it look and work like an XmlObjectSerializer. XmlObjectSerializer is an abstract class with only a few methods we need to implement.
Below is a sample of a class that will do just that.
namespace Microsoft.ServiceModel.Samples
{
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.Runtime.Serialization;
public class CFMessagingSerializer : XmlObjectSerializer
{
readonly Type objectType;
XmlSerializer serializer;
public CFMessagingSerializer(Type objectType)
: this(objectType, null, null)
{
}
public CFMessagingSerializer(Type objectType, string wrapperName, string wrapperNamespace)
{
if (objectType == null)
throw new ArgumentNullException("objectType");
if ((wrapperName == null) != (wrapperNamespace == null))
throw new ArgumentException("wrapperName and wrapperNamespace must be either both null or both non-null.");
if (wrapperName == string.Empty)
throw new ArgumentException("Cannot be the empty string.", "wrapperName");
this.objectType = objectType;
if (wrapperName != null)
{
XmlRootAttribute root = new XmlRootAttribute(wrapperName);
root.Namespace = wrapperNamespace;
this.serializer = new XmlSerializer(objectType, root);
}
else
this.serializer = new XmlSerializer(objectType);
}
public override bool IsStartObject(XmlDictionaryReader reader)
{
throw new NotImplementedException();
}
public override object ReadObject(XmlDictionaryReader reader, bool verifyObjectName)
{
Debug.Assert(serializer != null);
if (reader == null) throw new ArgumentNullException("reader");
if (!verifyObjectName)
throw new NotSupportedException();
return serializer.Deserialize(reader);
}
public override void WriteStartObject(XmlDictionaryWriter writer, object graph)
{
throw new NotImplementedException();
}
public override void WriteObjectContent(XmlDictionaryWriter writer, object graph)
{
if (writer == null) throw new ArgumentNullException("writer");
if (writer.WriteState != WriteState.Element)
throw new SerializationException(string.Format("WriteState '{0}' not valid. Caller must write start element before serializing in contentOnly mode.",
writer.WriteState));
using (MemoryStream memoryStream = new MemoryStream())
{
using (XmlDictionaryWriter bufferWriter = XmlDictionaryWriter.CreateTextWriter(memoryStream, Encoding.UTF8))
{
serializer.Serialize(bufferWriter, graph);
bufferWriter.Flush();
memoryStream.Position = 0;
using (XmlReader reader = new XmlTextReader(memoryStream))
{
reader.MoveToContent();
writer.WriteAttributes(reader, false);
if (reader.Read()) // move off start node (we want to skip it)
{
while (reader.NodeType != XmlNodeType.EndElement) // also skip end node.
writer.WriteNode(reader, false); // this will take us to the start of the next child node, or the end node.
reader.ReadEndElement(); // not necessary, but clean
}
}
}
}
}
public override void WriteEndObject(XmlDictionaryWriter writer)
{
throw new NotImplementedException();
}
public override void WriteObject(XmlDictionaryWriter writer, object graph)
{
Debug.Assert(serializer != null);
if (writer == null) throw new ArgumentNullException("writer");
serializer.Serialize(writer, graph);
}
}
}
-
I recently discovered a very impressive (and free) Silverlight slideshow control. I would recommend it over any Flash-based slideshow controls that I've seen so far (because this one's better--not just because I work here <g>)
Here's a sample:
Watch for a follow-up post on my JMPInline blog on the tricks I had to pull to get this Silverlight control working on Blogger while still pulling RSS photo feeds from PicasaWeb, despite the XSS-limitations imposed on Silverlight 1.0 controls.