Common Controls in Windows Installer UI

Notice the differences between the following two dialogs from the same Windows Installer package on the same Windows XP machine.

The first dialog is displayed when launching a sample .msi file using the msiwai.exe program I detailed before. The second dialog is displayed when the sample .msi file is launched from Windows Explorer, thus using the default handler, msiexec.exe. So why the difference?

The difference between the two executable is that msiexec.exe has an embedded manifest to bind to the Common Controls 6 side-by-side native assembly, while my sample application msiwai.exe has no such manifest and, thus, uses the last Common Controls version prior to Windows isolated application and side-by-side (WinSxS) support introduced in Windows XP.

If you open msiexec.exe in Visual Studio, for example, you’ll see a resource section called RT_MANIFEST. If you open the item identified as 1 as binary data you’ll see what looks like XML. When you extract it as msiexec.exe.manifest (or anything really, but the name is important for external manifests) and open it you’ll see the following:

<?xml version=1.0 encoding=UTF-8 standalone=yes?>
Copyright © 1981-2001 Microsoft Corporation –>
assembly manifestVersion=1.0 xmlns=urn:schemas-microsoft-com:asm.v1>

    <description> Windows installer setup service </description>

The <dependentAssembly> causes the loader to bind to the Common Controls 6 assembly which includes the rich controls that made their debut in Windows XP. Manifests allow you to isolate applications and use different versions of libraries at the same time for different applications, even redirecting version policies much like you can with .NET Framework side-by-side execution. You can also use manifests for registration-free COM.

Since my sample application wasn’t linked with a resource file originally it’s not straight-forward to add the manifest. You can, however, use similar content as that above, changing the name attribute from “MSIExec” to something else like “MsiWait”, and the <description> to something appropriate like “Bootstrap to wait for a previous installation to finish”. Save that to a file named msiwait.exe.manifest and save it in the same location as msiwait.exe. Now run msiwait.exe with a .msi file on Windows XP and newer and you’ll see a UI similar to the second dialog above.

Since the setup.exe bootstrap application that Visual Studio creates when building a Windows Installer project (if you’ve opted to build a bootstrap application) doesn’t embed a manifest either you can use that for the next procedure.

  1. In Visual Studio click on the File menu and Open.
  2. Browse to the setup.exe bootstrap application for a Windows Installer project, select it, and click Open. You should see tree view with nodes like Dialog, Icon, and Version.
  3. Right-click on the top node and select Add Resource.
  4. Click the Import button and browse to your manifest file similar to the one we created above, select it, and click Open.
  5. In the Custom Resource Type dialog enter RT_MANIFEST and click OK.
  6. Right-click on the newly created node in the tree view, select Properties, and change the ID to 1 (the manifest resource ID used by the loader for process defaults).
  7. Save the executable.

Now when you run the bootstrap application on Windows XP or newer Common Control 6 will be loaded instead. If you are using a theme like the default Windows XP theme you’ll see a dialog similar to the second one above.