The Old (New) Common Controls
The common controls provided by Windows are shipped as part of the OS in the Common Controls library. When .NET was first introduced we had the v5 version. When XP was released a new version (v6) was introduced. Applications that needed to run under W2K or XP had to target v5 while XP-only applications could use v6. v6 added many new controls and enabled theming. For example task dialogs, the replacement for message boxes, require v6. Ironically it isn’t even part of the framework yet, you have to use an addon.
Fast forward to today. .NET v4 only supports XP and above. Therefore if you’re writing a .NET application you can safely use the v6 controls. But guess what – .NET uses v5 by default.
Enabling the v6 Controls
Enabling the v6 controls is, unfortunately, not a simple check box. One approach is to make a specific API call (Application.EnableVisualStyles) before any user interface code. If you’re writing a WinForms application then the default template generates the necessary code but I’ve always felt like this was a hack. The code has to run before any code that might do anything related to user interface work otherwise the default v5 controls are loaded.
The better approach is to add an application manifest that specifically identifies the v6 common controls. This ensures that the proper version is loaded before any code is run. Here’s how it might look like:
<assemblyIdentity type=“win32“ name=“Microsoft.Windows.Common-Controls“ version=“220.127.116.11“
Adding a manifest is not hard. In fact if you are using UAC settings then chances are you already have one. But honestly this shouldn’t be necessary anymore. .NET v4 only supports XP+ so a .NET v4 application should load the v6 controls automatically. But alas this is yet to be the default.
Problems In Paradise
Unfortunately using a manifest to load the controls introduces some annoying problems. The first problem is that ClickOnce won’t work anymore. ClickOnce can’t handle dependent assemblies. I’ve already blogged about this issue.
The second, and probably more annoying, problem is that you’ll occassionally be debugging your application and find that the manifest seems to be ignored. This is most obvious when you try to use a task dialog in your code (say for error reporting) and you get an error trying to display the task dialog. The error will generally say something about needing the v6 controls. Checking the manifest will confirm that you have set the appropriate options. You’ll then probably have to run your app and use a tool like Process Explorer to see what DLLs are actually getting loaded (since VS doesn’t seem to display unmanaged DLLs in .NET apps anymore). You’ll find that v5 is in fact being loaded despite your manifest. What is going on?
Back in the VS2005 days (approximately) Microsoft bragged about how much faster the debugger was. They gained this speed boost by using the VS host process (vshost) to load programs to be debugged. In previous versions when you started the debugger your process would start and all the pre-debug processing would occur. When debugging was finished all the information was thrown out. When you started debugging again the information had to be generated again. vshost actually handles this now. vshost is loaded when the project loads and remains running until VS shuts down. This speeds up debugging greatly, but at a cost. Windows cannot tell the difference between your application and vshost so Microsoft had to write some code to cause vshost to emulate your process as closely as possible (even down to the configuration files). But at the end of the day vshost is ultimately responsible for running.
Back to the application manifest. If vshost loads DLLs before it reads your manifest file (which happens at arbitrary times in my experience) then it is possible that vshost will load the wrong DLL. In the case of the common controls vshost uses v5 by default. As a result if you are debugging your application through vshost and your manifest requests v6 controls then it might or might not work. I’ve had it work after 5 debug sessions and fail on the 6th. So the takeaway is that if you want to use the v6 controls then you need to disable the vshost process (Project properties -> Debug -> Enable the Visual Studio hosting process). Note that this only applies to Windows applications.
In summary if you want a XP+ style user interface then you’re going to have to use an application manifest to load the correct version of the controls. But this will prevent the use of ClickOnce publishing. It also means that you will likely have to disable the vshost process for debugging. I hope that Microsoft will fix this issue in a future version of VS. I’d like to see an option for Windows projects that allow us to select the version of the controls (and perhaps other libraries) that we want to use. We shouldn’t have to edit manifest files and hack around tools to use what should be the default settings going forward. If you agree with me then please cast your vote at the Connect site on this issue.