3

I'm using WiX 3.8 and trying to update my existing .config file on minor update but I'm having difficulties understanding how to achieve this.

I created a custom action to read values from the existing config file but can't figure out how to insert them into the new file?

I followed this article : Having WiX upgrade a config file with missing items (and subsequently this one : How can multiple elements be added to an XML config file with wix?) but settings don't seem to be getting overwritten with previous values, can anyone give me a pointer please?

Basically I want to preserve the settings entered by the user during installation but overwrite the rest of the config if it has changed from version to version.

Community
  • 1
  • 1
Mike
  • 369
  • 1
  • 6
  • 24

2 Answers2

2

In a nutshell, this is a huge weakness of Windows Installer. Natively MSI has no support for XML operations. At it's core, Windows Installer treats files atomically where as an XML file is in a sense like an entire registry hive.

WiX adds in XML transforming capabilities to solve the first problem but the second problem is really impossible to solve. You'd have to have a copy of the original XML, the current XML and the proposed XML and then you'd have to have business rules to know what to merge and what not to merge.

In order to avoid this problem in the first place, what I personally suggest is to have 2 XML files. One installed and fully owned by the installer ( stock.xml) and one not touched by the installer and owned by the application (override.xml). Then in your XML reader have the contents of the override.xml take precedence over the contents of the stock.xml. In this way the installer can always do what it does best ) install files without having to do complicated data processing.

Christopher Painter
  • 54,556
  • 6
  • 63
  • 100
2

I currently do this with a combination of custom action and XmlConfig.

The custom action is run after CostFinalize and reads current values from the config file(s) and saves them in public properties.

  string configFile = Path.Combine(session["INSTALLLOCATION"], "app.exe.config");
  ExeConfigurationFileMap map = new ExeConfigurationFileMap();
  map.ExeConfigFilename = configFile;
  Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
  session["OLD_PRESERVEDVALUE"] = config.AppSettings.Settings["PreservedValue"].Value;

then I have an XmlConfig entry like below which sets the preserved values from the public properties:

   <Component Id="RestoreOldPreservedValue" Guid="<GUID>" >
   <Condition>OLD_PRESERVEDVALUE</Condition>
   <CreateFolder/>
   <util:XmlConfig
       Id='RestoreOldPreservedValue'
       Action='create'
       On='install'
       Node='value'
          ElementPath='/configuration/applicationSettings/app.Properties.Settings/setting[\[]@name="PreservedValue"[\]]/value'
            File='[#app.exe.config]'
            Value='[OLD_PRESERVEDVALUE]'>
        </util:XmlConfig>
     </Component>

My next iteration will be to have the custom action create entries in the XmlConfig table directly.

The ultimate solution would be a WiX extension that populates a custom table and schedules a custom action which saves the values to be preserved after CostFinalize, and then another custom action that restores the values after the new config file(s) have been copied by the installer.

wta
  • 78
  • 7
  • thanks for your input, I ended up using the exact same approach through trial and error! – Mike May 28 '14 at 11:28