One of the features of Windows that (to me at least) seems to get comparatively little attention are manifests. If you are not familiar with manifests, they are XML files that communicate with the loader to express certain bits of metadata.
Manifests can be embedded inside of an executable file (in an application resource), or they can be placed side-by-side with the resource. We will deal with how to embed this later; for now, let's just look at the contents and what they do. Let's dissect the manifest that is embedded within Windows Media Player.
So, the first question is, how can I get at the manifest, if it is embedded? There are a couple of different options. First, you can use Visual Studio 2005. From the File menu, select open, and then select file. Point to the executable file that you wish to open (in this example, wmplayer.exe). You will see a list of the resources embedded in the file. One of the folders is labeled RT_MANIFEST. If you open this up, you will see a single file with the number 1. If you double click to open this, you will see the file in a hex editor, with the contents scrunched up to the right. I find this rather difficult to read, so what I do is right click on the 1 entry, select export, and save it someplace with the name wmplayer.manifest. This will be an XML file that is much easier to work with. (You could also name it wmplayer.xml.)
Another way to extract a manifest is to use the mt.exe tool, which is included with both Visual Studio and the Platform SDK. Assuming that mt.exe is in your path, you can enter: c:\Windows>mt -inputresource:"c:\Program Files\Windows Media Player\wmplayer.exe" -out:"c:\users\<user name>\Desktop\wmplayermt.manifest"
Let's take a look at this manifest:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assemblyIdentity version="184.108.40.206" processorArchitecture="*" name="Microsoft.Windows.WMplayer" type="win32"></assemblyIdentity> <description>Windows Media Player</description> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="220.127.116.11" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"> </assemblyIdentity> </dependentAssembly> </dependency></assembly>
The interesting thing that is going on here is the dependency on common controls. This is how side-by-side assemblies work on Windows. This is specifically addressing comctl32.dll. Rather than forcing an application to use the latest version of the controls, which may provide new features that the application is not prepared to deal with, we can provide the exact same behavior for existing applications, and provide a mechanism for applications to vote themselves in to using the new features.
Let's take a look at how the loader is going to interpret this. If you browse to c:\windows\system32.comctl32.dll, right click on this file and select properties. The Details tab will show you the version number. In my case, I see 5.82.<Vista major build number>.<Vista minor build number>. 5.82 - that's a version that has been around for a while, no?
So, where is the 18.104.22.168 version that I am trying to vote myself in to? They are in the Windows Side-by-Side directory. If you browse to c:\windows\winsxs, you will see a host of directories for side-by-side assemblies. You should see a directory called x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.5505.1_none_7b15be8ba7c6f2d2, as well as one for the 5.82 implementation. (Notice the file name contains the public key token specified in the XML.) When you vote yourself in to the 6.0 implementation, the loader brings in the file from this directory, rather than the 5.82 version. If you check the version number of this one, I see 6.10.<Vista major build number>.<Vista minor build number>. And, as a result of this manifest, I will be using the 6.x common controls, which include visual styles, rather than the Windows 2000-looking common controls.