Thursday, May 29, 2008

Of course, it's also possible to disable it manually via Start->Control Panel->System->Hardware->Driver Signing. But the C code from the link above allows an installer to disable it automatically. For the vertical application I maintain, I bundle every possible A/D board driver into an all-in-one InstallShield installation, and I have to use a variety of tricks to make them all install silently. This is the latest such trick.

Visual Studio 2005 SP1 has different CRT (C Run-time) and MFC libraries than non-SP1 Visual Studio 2005 does (also known as VS2005 RTM, or release to manufacturing). This can wreak havoc in light of XP's strong support for (and enforcement of) SxS (side-by-side) DLLs, which allows different applications to use different versions of the same DLL. Or, in the more complex case I encountered, a single application may end up needing to dynamically link to both the RTM version of MFC and the SP1 version of MFC.

I ran into this while trying to use some ActiveX controls out of National Instruments' Measurement Studio. Measurement Studio needed the RTM version of MFC, but my Visual Studio 2005 SP1 would only create applications with the SP1 version of MFC. And they conflicted, generating "activation context" errors.

To handle SxS, Visual Studio 2005 introduced the concept of manifest files, which specify precisely which version(s) of which DLL(s) are required. There is even a mechanism to automatically promote to using later versions of required DLLs. No matter the combination, I couldn't get my MFC application to work with Measurement Studio, because I of course did not have the source code to Measurement Studio to recompile it against the SP1 version of MFC. As one blog author put it, in the course of trying to solve DLL Hell (for the user), Microsoft ended up creating Manifest Hell (for the developer).

So my solution was to use ATL instead, and let Measurement Studio use the RTM version of MFC.

In an MSI, don't ever delete a component unless you plan to make it a"major upgrade" (change of both product and package GUIDs) rather thanjust a "minor upgrade" (same product GUID, different package GUID). If you try, msiexec will fail with "another version of this product is already installed". It was particularly frustrating for me because I use InstallShield to build an MSI wrapped inside InstallScript, and InstallShield was silently suppressing the error and just notinstalling anything.

To achieve the same effect as deleting the component, I just deleted all the files within that component instead, and that worked fine.