Hint: Be generous with upgrade codes

Major upgrades work across products by associating them with a single upgrade code: Version 1.0 of a product has a different product code than version 2.0 but both share the same upgrade code. The FindRelatedProducts action and MsiEnumRelatedProducts function find any products on the system with a particular upgrade code. The RemoveExistingProducts action then uninstalls the (usually older) products as part of the major upgrade cycle.

Note that FindRelatedProducts and MsiEnumRelatedProducts explicitly support finding multiple products installed on the system simultaneously. MSI doesn’t try to force you to use the same upgrade code only for products that are upgraded by major upgrades. That means it’s possible to use the same upgrade code for products that aren’t major upgrades for each other.

However, the Upgrade table supports only version and language as ways of narrowing down the products it finds. So if you use the same upgrade code for multiple products that can be installed simultaneously, FindRelatedProducts doesn’t have a way to filter out the ones you don’t want removed in a major upgrade.

You can use a custom action to remove product codes from the property specified by the UpgradeVersion/@Property attribute. Just schedule it to run after FindRelatedProducts. The cost is that you have to maintain by hand any such product codes and carry them from version to version.

The Upgrade table and FindRelatedProducts action let you search on multiple upgrade codes in a single product. So it’s always safe to use more upgrade codes if you think you might support having products side-by-side in the future — just use multiple Upgrade elements to detect and uninstall them via major upgrade.

In short, if you have products are never going to be installed at the same time, you can safely use the same upgrade code. But if you have products that might need to be installed simultaneously, give them separate upgrade codes. (Upgrade code GUIDs are cheap when you buy them in quantity from reputable online retailers.) And always test your servicing strategy before you release a product: Some things can’t be fixed in a patch.

VirtualBox 1.6.0 setup another example of the second law of thermodynamics

VirtualBox, the desktop virtualization product acquired by Sun Microsystems in February, shipped version 1.6.0 on Friday. I previously mentioned VirtualBox in my blog post on setup testing with virtual machines. I lauded their clean setup and low custom-action count.

Unfortunately, the latest version hasn’t kept up that standard of Setup Goodness™.

The x64 package isn’t marked with the x64 platform template. I suspect that was intentional, as it allows the package to be opened and then canceled with a more friendly error message than the stock message Windows Installer provides. Nonetheless, it throws a bunch of ICE errors because MSI treats the package as 32-bit.

They also added a custom action: ActionRemoveDataFiles. Nothing to get too worked up about, but it’s like they tried to cram into one CA all the possible wrong things you can do with CAs:

  1. It’s VBScript. Evil. One day after release, a user started a thread on the VirtualBox support forum about getting a 2738 error on Windows Vista.
  2. It’s an immediate CA that modifies machine state.
  3. As an immediate CA, it runs impersonating the installing user, so attempts to delete files outside that user’s profile will fail unless the user started the setup as an administrator.
  4. It doesn’t have a “matching” rollback CA to undo what it does.
  5. It tries to “clean up” user data — including the virtual machine and disk configuration.
  6. It tries to clean up all users’ data, even those who aren’t logged in. That’s going to fail for roaming profiles, because the MSI server doesn’t have permissions to the remote data.
  7. It’s scheduled in InstallExecuteSequence but shows message boxes to prompt the user for permission to clean up files. CAs scheduled in InstallExecuteSequence should never show UI; all UI should be handled via CAs scheduled in InstallUISequence or via dialog boxes in the Back/Next wizard sequence.
  8. The CA’s condition in InstallExecuteSequence uses “UILevel>2” presumably so the message boxes are shown when the user uninstalls VirtualBox from Add/Remove Programs (Programs and Features on Vista). Unfortunately, it violates the contract MSI provides for “basic UI” mode. Using the /qb or /passive switches is commonly used in automated installations to show modeless progress UI without ever showing a modal prompt. ActionRemoveDataFiles will show modal UI during any uninstall other than with the /silent or /qn switches.
    To be fair, the shell folks who designed ARP and the MSI folks are partially responsible: They didn’t provide a UI level that says “I’m uninstalling interactively from ARP, so it’s OK to show some modal UI.”

Worst of all: This particular custom action makes it way too easy to delete gigabytes of virtual machine configuration and drives with no more than an accidental Yes button click. <shudder/>