Files not installed when applying a Minor Upgrade and how to troubleshoot it

While analyzing one of customer issues reported to me, I came accross an interesting problem which – having prior knowledge how it works – would be solved in minutes, not in hours and days as it really took.

The problem

The customer reported that an MSP patch created by RayPack works fine, but not really up to his expectations. While being considerably smaller than a full MSI upgrade, the installation took a while because the previous version must have been uninstalled and installed again in the background. This is basically the idea how major upgrades are working, and the customer wanted to switch to a typical patching, which (depending on conditions) would mean going for a small update or a minor update.

We suggested to him that while usually not recommended in packaging projects, minor upgrades are different from major upgrades that they must not change ProductCode, aside of some other limitations. The customer tried it anyway and reported that our suggestion initially helped, only to report some minutes later that it actually hadn’t. The new version of product had been apparently installed (and visible in ARP), but the files were not updated – new files were still missing, binary changes were not applied etc. There were no errors during update, the msiexec exit code was also fine.

Another issue was, that after installing the patch, self-repair stopped worked for random components. Removing certain key path resources triggered repair, while for others it did not work. Weird.

Analysis + findings

Our analysis indicated that it was not actually a problem with the patch itself, but more like with the way Minor Upgrades are working, and thereof the problem could be easily reproduced by installing the second MSI containing a minor upgrade with a command line:

msiexec /i <path> REINSTALLMODE=vamus REINSTALL=all /qb

(note: vamusis non-standard, but was chosen for troubleshooting to also overwrite files in the same version). It is important to indicate that the cached MSI has to be recached from source (thus v in the reinstall mode), otherwise you obviously can’t install an MSI as minor upgrade.

We don’t do that many minor upgrades, but enough to be aware of certain limitations, including that names of MSIs must be the same (so that Product2.0.msi cannot do a minor upgrade of Product1.0.msi etc.), the feature trees must remain unchanged, some other conditions apply (more on msdn sites).

If you ever encounter a problem like that, have some time saved by this ultimate troubleshooting:

If you suspect your minor upgrade did not work correctly, go to the log file and look for the string SELMGR, for example:

MSI (s) (70:BC) [17:59:04:464]: SELMGR: ComponentId '{9EAF8350-6D60-4C2A-8626-797E8E5423B7}' is registered to feature 'Complete', but is not present in the Component table.  Removal of components from a feature is not supported!
 MSI (s) (70:BC) [17:59:04:464]: SELMGR: Removal of a component from a feature is not supported

Well, this clearly indicates the source of the problem. There used to be a component with a documentation file having product version 5.2 in its name, while the old product had a file with version 5.1. Since it was in the same time a keypath component, it effectively meant that the new installation removed an existing component. This is not supported by minor upgrades!

A picture showing how the machine policy is shown in the log, followed by two SELMGR lines and then breaking the installation.

This is how the machine policy is shown in the log, followed by two SELMGR lines and then breaking the installation.

Funny thing is that the Windows Installer engine does not care about it. Once it throws SELMGR, it kind of breaks the installation, and returns success as its exit code, although the product is in invalid state and possibly with broken self-repair.

Troubleshooting and proper exiting

In order to have a proper error displayed when an MSI installation is broken due to fauly minor upgrade, it pays off to set a property MSIENFORCEUPGRADECOMPONENTRULES  to 1 (there are also ways to set it globally, but I would not recommend it). This way, when a minor upgrade cannot install files due to minor upgrade conditions not met, the whole installation returns an error, and at least gives the packages an immediate chance to know that it failed.

Final thoughts

The limitations of minor patching are effectively rendering it useless for anything other than a simple hotfix. The following two limitations are for me a complete show stopper, and since patching is problematic enough on its own I would recommend to simply stick to major upgrades. Here are my two blockers:

  • Not being able to change the name of the database
  • Not being able to remove files (there are workarounds with setting false conditions for respective components + marking them as transitive, but it does not solve all cases for example of selective removal)

Leave a Reply