Common Controls in Windows Installer UI

Common Controls in Windows Installer UI

  • Comments 8

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.

Leave a Comment
  • Please add 3 and 5 and type the answer here:
  • Post
  • Heath,

    I have a related question.  Can you use a method similar to what you describe override the default Progress Dialog?  I have used MSISetExternalUI, but it only seems to work if the application directly launches the MSI with MSIInstallProduct, and does not work if the MSI is wrapped with another EXE.
  • John, that is to be expected. MsiSetExternalUI works only for the current process. You could perhaps emulate a progress bar if it matters enough by silently running the pre-reqs.
  • Hi Heath, Is there anyway to toggle a button's "enabled" state from a CA? If so, is it done via GetWindowEx and passing the name of the button control? If so, what is the name of button controls on Windows Installer forms, i.e. text boxes are all named "RichEdit20A". Or is there a method available via the API that can do this? Thank you, Mike Williams Hummingbird, Inc.
  • You should not attempt to use control IDs because dialogs are built dynamically and IDs can change. Instead, you can use MsiProcessMessage to disable the Cancel button. At, read about the INSTALLMESSAGE_COMMONDATA message.

  • What if it is not a Cancel button and using Conditions for Enable and Disable actions for any button do not work?
  • Mike, if you need more advanced UI you should considering writing an external UI handler but this can be a more daunting task than ensuring that your installation works during rollback. That's the most important thing, because one of the great features of Windows Installer is it transactional nature. If a CA does not support rollback when it should, that CA should be rewritten correctly to support rollback, or you're only hurting the end users' machines.

  • PingBack from

Page 1 of 1 (8 items)