I ran into an interesting scenario related to Windows Installer major upgrades recently and I wanted to summarize some things I learned from this experience and from the MSDN documentation in case they are useful for others. In the scenario I ran into, I implemented a Windows Installer major upgrade to automatically remove older versions of my MSI behind the scenes as part of the installation process for newer versions of my MSI.
I scheduled the uninstall of the previous version after InstallFinalize due to the assembly publishing issue described in this blog post. This scheduling resulted in the newer version being installed before the older version was uninstalled. However, I needed a way to prevent some of the custom actions in the older version from running during this major upgrade uninstall step because they would interfere with the already installed newer version.
Fortunately, I was alerted to the existence of the UPGRADINGPRODUCTCODE property in Windows Installer. When Windows Installer removes an older version of a product in the RemoveExistingProducts action as part of a major upgrade, it sets the UPGRADINGPRODUCTCODE property on the command line for the uninstall action. This property can be used by the MSI being uninstalled to differentiate between a standard uninstall initiated by the user (via Add/Remove Programs for example) and an uninstall initiated by a newer version of the MSI via a major upgrade.
What I ended up doing was adding a condition of (NOT UPGRADINGPRODUCTCODE) in the InstallExecuteSequence table for each of the custom actions that I wanted to prevent from running during the major upgrade. This allowed my major upgrade to work as expected and prevented the uninstall of the older version from breaking the newer version. It also allowed a standard uninstall of the MSI to correctly execute these custom actions.
Thanks to Heath Stewart for letting me know about the UPGRADINGPRODUCTCODE property to help out in this scenario.