Mailbag: How to retain user-customized files during a Windows Installer major upgrade

Question:

I have an application that installs some .config files that users can customize.  I want to implement a Windows Installer major upgrade to install new versions of my application on systems that have an older version installed.  During the upgrade, I want to keep any customizations that users have made to the .config files instead of replacing them with new versions of the files.

How do I configure a major upgrade so that customized .config files will not be replaced during the upgrade process?

Answer:

The first thing to keep in mind is that a Windows Installer major upgrade is simply an install operation and an uninstall operation combined into a single installation session.  Whether or not .config files get replaced depends on how you author the information in your MSI.

There are a couple of key things you need to do to enable this behavior:

1. Place each .config file in its own component and mark the .config file as the key path of the component.

Doing this will ensure that Windows Installer will use unversioned file replacement logic when deciding whether or not to replace this file in the install of your new version.  The high-level summary is that Windows Installer will compare the creation time of the component's key path file with the last modified time if both the old and new versions of the file are unversioned.  If they differ, then Windows Installer assumes the user has modified it and it will not replace it.

2. Schedule the RemoveExistingProducts action in the new version of your MSI after the InstallFiles action .

Doing this will make sure that the new versions of all of your components are installed before removing the old version of your MSI.  When the new versions are installed in this sequence, your components will have their reference counts incremented to 2, but the .config files will not be replaced unless they are unmodified (because of the unversioned file replacement logic described in item 1 above).  Then, when the old version of your MSI is uninstalled afterwards during the RemoveExistingProducts action, the reference counts will be decremented back to 1, but the files will not be removed the system because the reference counts are not yet 0.

If you schedule RemoveExistingProducts before InstallFiles, then the uninstall of your old version will cause the component reference counts to reach 0, and the files will be removed from disk.  When the new versions of your components are installed afterwards, the files will be replaced with the new versions.  This will cause your users to lose any customizations they have made to their .config files.

The .NET Framework 2.0 SP1 and SP2 are implemented as major upgrades of the original version of the .NET Framework 2.0.  It has the same requirement of keeping any customizations the user has made to .config files.  The .NET Framework 2.0 SP1 and SP2 installer schedules RemoveExistingProducts in the following specific order because otherwise, it would encounter an ICE63 warning: