tags:

views:

1453

answers:

2

I have an application with several files that contain configuration parameters and other data that changes as the user uses the application. These files can change with newer versions of my software, but the user can also modify them (or they may be changed by the application itself). Basically, I'm looking for a solution to prevent the users' changes to these files from being overwritten but also a way to install the potentially updated files when the user upgrades my software.

With RPM on *NIX you could use the %config function to define a file as a configuration file and RPM would then rename the existing file (if it existed) and install the new one on an upgrade (maybe not ideal, but I could live with something like this for WiX).

I'd like to install my config files to a subdirectory or even a different name (e.g. default.cfg) and then use the <CopyFile> element in WiX to copy the files to their correct locations. This way, the default files would get removed on install and overwritten on an upgrade, but the actual user files would stay the same. Unfortunately with <CopyFile>, Windows Installer still wants to manage (and remove) the destination file.

I've also considered using the QtExec action in WixUtilExtension to basically do "copy default.cfg reallocation.cfg" but this wouldn't quite work and it is a bit of a hack.

What is the correct way to handle this?

+2  A: 

I think there is no "clean" way to do this, because a msi project must be able to uninstall itself completely by design. I think the best way to solve this, is by using a custom action which executes a batch file and put your configfile update logic in that batch file. The custom action looks like this (only relevant parts):

<Directory Id="MYDIR" Name="MyDir">
    <Component Id="update.cmd" Guid="YOUR-GUID">
        <File Id="update.cmd" Name="update.cmd" KeyPath="yes" 
                Source="source\update.cmd" />
    </Component>
</Directory>

<CustomAction Id='RunUpdate' Directory='MYDIR' 
        ExeCommand='[SystemFolder]cmd.exe /c update.cmd' Return='ignore'/>

<InstallExecuteSequence>
    <Custom Action='RunUpdate' After='InstallFinalize'>NOT Installed</Custom>
</InstallExecuteSequence>
Wimmel
+2  A: 

My recommendation is usually to have the user editable content in a separate file and manage that via the application instead of the install. That also means the separate file is "user content" and should be left out of the install.

I've found trying to do migration of user data declaratively to be deceptively difficult. Trying to do it at setup time when you need to think through install, uninstall, repair, patching and rollback for all of those cases only makes it worse.

For example, what does the RPM behavior do on "repair". Copy the user data out of the way and replace it with a good file? That's probably correct 60% - 80% of the time. And uninstall, should the file be removed? That's tricky if the user is going to just upgrade to the next version.

Again, better to let them decide what to do with their tweaks to the configuration. IMHO.

Rob Mensching