Thursday, October 07, 2004

Handling Application Data

Recently, I had initiated a thread in the WIX users list regarding the inclusion of application data in the MSI package. My thanks to Riko, who shared his views on that. It has always been tricky and will continue to be a tricky situation to deal with application data. Most applications include their application runtime and configuration data as registry entries, INI or XML files. An unassuming developer might package these registry entries with the Main application's component, as they are dependent on the main application. This would work fine during the first install, but would cause significant issues during an upgrade. Geoff has blogged one such scenario. This blog tries to capture some of my thoughts regarding such Application Data.

For starters, lets look at what happens when you include the application data in the MSI package. The user, to configure the software the way they want, usually modifies these entries. Many times, it is the application itself that changes or writes data to the registry, INI or XML files to persist the configuration state of the application. Assuming we have included such files and registry entries grouped in the same component as the main executable. We can argue that it would be a good design as these entries are logically bound to the application and have no sense existing as a standalone unit. The application would roll out pretty smooth and will have no problems until you hit a point when you have to upgrade. Let us consider a minor upgrade, no major changes, a few DLLs modified and couple of executables added. Let main executable file have its version bumped. As the executable is the key file of the component, it qualifies for an upgrade. Let us also consider changes made to the XML files and a few Registry entries to accommodate the change. During an upgrade, all hell would break loose. The registry would be overwritten and the registry might be left with conflicting entries and some XML files would updated, the others may be left untouched as it would have a greater modified date. If you are really unlucky, the testing team might not quite get the tests done right. The Result: Total Chaos.

So how should these things be handled? The answer to this question is not straightforward and seems to be pretty tricky. The most ideal scenario would be to let the application handle its own configuration. The application should be able to create these registry entries and XML files during the first run. The setup developer then has to merely author the RemoveFile and RemoveReigstry tables to get the files out during uninstallation. As far as XML handling is concerned, it is best left to the application to handle it. MSI does not support XML handling and we need robust custom actions to do it for us. Handling XML data/SQL Data during upgrades can only be done using custom code. It would be desirable if this code is present on the application's end and not on the installer's end. If you do have to include the application data in the MSI package, the following guidelines may be useful.

1) Identify and Isolate the Application Data:
Clearly identify the resources like registry entries, INI Files and other configuration files that are to be used by the application. Use the INIFile table to author INI Files. Avoid including the INI file itself in the File table. Once identified, include the application data in a separate component. Use multiple components, if necessary.

2) Minor Upgrade and Uninstall Scenario:
If the application creates extra files or registry entries, ensure that the RemoveFile and the RemoveRegistry tables are populated. The problem is that these tables are referred to even during installation of the component. So you would have to set the Never Overwrite bit of the component to make sure that this component is never marked for an upgrade. Code the upgrade logic for the application data in to the application itself. In the unlikely event of it not being feasible, write custom actions to achieve the same. Avoid writing custom actions for tasks that can be handled by the application.

3) Major Upgrade Scenario:
Certain applications like InstallShield X, schedule the RemoveExistingProducts action right before the InstallInitialize action. This is not the most efficient placement for this action. The most efficient placement for this action would be after the InstallFinalize action. I will talk about this in detail another time, if you haven't figured it out as yet. If the authoring tool places the RemoveExistingProducts action before InstallInitialize, manually schedule it after InstallFinalize. There are certain custom actions in InstallShield X (I guess Component Services) that are not very happy with this placement, although I am not very sure about this. In these cases, you would have to use related locator (AppSearch, RegLocator, IniLocator, etc.,) and signature tables to get save the information into properties and reuse them in the install. This is a very elaborate and time-consuming exercise. The shorter and a devilish way to get around this is to write custom actions to read the values in the registry and store them in a text file, back up your application data files and restore them back with another set of custom actions. As unscientific as it might sound, a lot of people have used it to get out of this mess.

Rob is currently working on a similar blog entry. I can't wait to read on what he has to say about this.

1 comment:

Deepa Iyer said...

Hey Vagmi,

That s a real good one.. I know how painful it is...:-) should be really useful when I join as a release engineer elsewhere....:-)