Mailbag: Why does my custom action that depends on the VC 8.0 CRT fail on Windows Vista?

Question:

I have built an MSI-based setup for my application that includes the merge module for the Visual C++ 8.0 CRT (msvcrt80.dll).  In addition, the MSI contains a custom action that has a dependency on the Visual C++ 8.0 CRT.  I have been able to successfully install this MSI on Windows XP, Windows Server 2003 and Windows Vista in the past.

Recently, I updated my development system to Visual Studio 2005 SP1.  After I did this and rebuilt my MSI, I am no longer able to install my MSI on Windows Vista.  The custom action that depends on the VC 8.0 CRT no longer runs correctly.

Why did this error just start happening, and how can I resolve it so that I can install my MSI correctly on Windows Vista?

Answer:

As I previously described in this blog post, an MSI that installs any of the VC 8.0 runtime files and also includes custom actions that depend on the VC 8.0 runtime files can run into problems.

To briefly summarize that blog post, on Windows Vista, the VC 8.0 runtime files are installed as global assemblies using the MsiAssembly and MsiAssemblyName tables.  When global assemblies are installed during an MSI-based setup, they are not fully published and available for use on the system until after the InstallFinalize standard action.  This means that if an MSI installs the VC 8.0 runtime files and also includes custom actions that depend on the VC 8.0 runtime files, then the custom actions must be scheduled after InstallFinalize in order to be guaranteed to not run into dependency issues on Windows Vista.

The reason why the MSI happened to install correctly on Windows Vista prior to updating your development system to Visual Studio 2005 SP1 is that Windows Vista includes the .NET Framework 2.0, and the .NET Framework 2.0 installs the VC 8.0 CRT (msvcrt80.dll).  This means that the CRT was already present on the system and the custom action in your MSI was able to run correctly as a result.  However, once this MSI is rebuilt using Visual Studio 2005 SP1, the custom action now depends on the VS 2005 SP1 version of the VC 8.0 CRT, which does not ship with the .NET Framework 2.0 and is therefore not on Windows Vista by default.  In this case, your MSI will install the CRT as a global assembly, and the CRT will not be fully published and ready to use until after the InstallFinalize action.

In order to resolve this issue, you will need to do one of the following:

  • Compile your custom action DLL with #define _USE_RTM_VERSION in order to cause it to always depend on the originally released version of the VC 8.0 CRT, regardless of whether or not you have Visual Studio 2005 SP1 installed
  • Schedule the custom action as a commit custom action so it will run after InstallFinalize and you can be sure that the VC 8.0 CRT will be fully published by your MSI
  • Statically link to the VC 8.0 CRT when building the custom action DLL
  • Remove Visual Studio 2005 SP1 from your development and build system so that the custom action DLL will not depend on the SP1 version of the CRT
  • Re-design your setup so that it uses Windows Installer standard actions where possible and ideally does not require a custom action in the first place (if possible)

<update date="5/20/2007"> Added an option to compile the custom action with the _USE_RTM_VERSION variable defined </update>