We have been using Windows Installer (WI) based setups for all of our newer applications. I used to use Wise, but I have migrated our installers to InstallAware. Why I made that change will be another blog post, but needless to say I had very good reasons to make the switch. When we release a new version or upgrade for one of our applications, we do full installs. We don’t do patches.
WI technology supports the distribution of patch files. If you are only updating one or two files, the patch file will only contain what has changed, greatly reducing the size of the installable bits needed to be distributed. I did use patch files when I first started doing WI based setups, but I abandoned the practice early on. Patches were hard to automate as part of the build process and they had to account for cumulative changes. The other drawback was that they could add files, but not remove them. Another drawback was that it yet another file extension, .msp instead of .msi, to explain to the users.
I decide to have the installers upgrade in place. When a new version was installed over a previous version, the previous version would be silently uninstalled, then the new version would be installed. This basically gives you a clean slate per install, which is great because you only install the files that are needed and the dependant objects will be up to date. The bad part is that the user settings will be removed as part of the previous versions uninstall.
What I needed to do was to persist the user defined settings. Consider a web application, if all of the settings are in the web.config file, then you just need to keep that web.config file around. The simple solution is to tell the installer not to delete that file on the uninstall. There’s a couple of problems with that approach. The first one is that the new install is a full install and the user gets to pick the destination. They may want to put the web application in a different folder or drive and I didn’t want to take that option away just to make my job easier.
The other drawback was far more serious. I could keep the web.config around between installs, but what if the new version added content to the web.config file? You don’t want to save the old settings and lose the new settings. That could cause hard to diagnose bad things to happen. What was needed was the ability to merge selected content from the old web.confile and into the new web.config. You can do many things with WI technology and InstallAware provides powerful functions, but this is a task best left outside the installer code.
I decided to write a Win32 command line app that would be able to save the old web.config and merge selected values from that file into the new one. The installer would be include that file and be able to run it without permanently installing it. I could have used C# with .NET (and I even had most of the code already written), but I didn’t want to deal with .NET security issues or make the .NET Framework a prerequisite for non .NET based installs. Delphi 2007 provided everything that I needed.
From the installer, I call this app just before the previous version is uninstalled with a command line parameter to designate which app is being installed. It will locate the current web.config file for that application and copy it to a folder in the user’s temp directory. I always have our installers write the location of the install folder to the registry, it makes tasks like this much simpler. After the new version has been installed, I run the app one more time, with a “-restore” command line parameter. It locates the cached copy of the old web.config and the new web.config and updates the new web.config file with the settings that need to be persisted across installs. Once that task is complete, it removes that temporary folder.
The app knows what settings to use from rules encoded into the source code. I could have used a file to store a list of settings to persist, but that would have made the installer a bit more complicated. It’s fairly easy to run an app from the installer without actually installing it, but if you want it to have it read an external file, then you need to make sure that file is in a place where it can be read from. That comes one more part of the installer to be tested and the mechanism for handling that would be specific to installer tool used. By making the app contain the rules it needed to follow, running it from the installer becomes a trivial task.
The other advantage of having a separate app to handle to the saving of the user settings is that the code is much easier to test and debug. It becomes a modular piece of the install and can even be unit tested in a scriptable manner. This type of code can be easily adapted to the types of application. I use a similar type of program to persist settings and current run start for some of our Win32 service applications.