1
votes

We recently added a new application setting (not user setting) to the app.config (URL to a logging server) of our legacy winforms application (.Net 4.6.1).

Old version was 1.0.3, we changed the version of all assemblies to 1.0.4 and in the Setup project (Visual Studio 2017 Installer Project) changed the version to match which gave up the pop-up to change the product code, which we did.

The install runs correctly (other things were changed too by the way, and those changes are correctly in the new version), but our new app.config setting is not. Curiously, if you manually delete the config file and re-run the app, it re-creates the config file which causes the new setting to appear. Any idea what's happening here?

Thanks!

1
Are you using WiX?Stein Åsmul
No, Visual Studio 2017 Installer Project Extension for Visual Studio 2017Hershizer33
I am afraid I don't use VS2017 Installer projects much, and I am not aware of any features for XML file updates in such projects. WiX is a very good toolkit to do anything you need for deployment. Some quick start suggestions in case you are considering migrating.Stein Åsmul
Visual Studio installer projects are inflexible. They author every single file as a key file in it's own component and hides the very concept of a component. It also uses the default file versioning rules. This explains the behavior you are seeing.Christopher Painter

1 Answers

1
votes

You might not be using WiX, but I'll just add what I wrote before I noticed that you didn't add WiX as a tag. Got to learn to read.


This might be the most common problem of all for MSI / WiX deployment, along with wiped out config settings during major upgrade. I assume you have set the app.config file permanent during installation to preserve it during major upgrade?

What is likely happening is that you have installed the config file as a file, but it should be installed as a bunch of XML configuration settings that can be merged into the destination file instead.

The MSI file versioning rules attempt to preserve non-versioned files that have been modified after installation. Accordingly a non-versioned file will not be overwritten if the create and modify dates of the file are different on upgrades. Your file will appear untouched without the most recent, desired values. It has been "preserved".

You can update your WiX source to set the required values using the appropriate WiX XML elements. There are two different elements that are relevant:

With regards to the differences between these two elements, I quote Bob Arnson (WiX developer): "You can do everything (and more) that XmlFile supports with XmlConfig but it requires extra authoring that's not necessary with XmlFile. XmlFile is best at modifying XML files that you're installing (e.g., to add an attribute reflecting the installed path of a file); it can't remove the modifications at uninstall time but if your setup installed the file, it will be uninstalled anyway. XmlConfig is best at modifying shared XML files because it supports uninstalling the modifications." (source).


I find this XML stuff quite fiddly, and I may not use the latest and greatest techniques, but here is a quick sample. Test thoroughly - particularly uninstall and upgrade scenarios - limited testing done on my part:

Here is my test XML file (that is actually installed as a file and then updated). Do check the encoding of the file you save - some issues with encoding have been reported - not sure what the current status is:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <ExistingConfig>
    <bindingRedirect oldVersion="0.0.0" newVersion="0.0.0" />
  </ExistingConfig>
</configuration>

Here is the WiX snippet that will update the file (and install the file). Put the above XML test file next to your WXS source file, or specify the correct source path before building your MSI.

<Component Feature='ProductFeature'>

 <!--Installs the base file-->
 <File Source='app.config' />

 <!--Create New Element-->
 <util:XmlFile Id='XmlSettings1' File='[#app.config]' Action='createElement' 
               Name='MyConfig' ElementPath='//configuration' Sequence='1' />

 <!--Set New Value-->
 <util:XmlFile Id='XmlSettings2' File='[#app.config]' Action='setValue' 
              Name='newVersion' Value='6.6.8' ElementPath='//configuration/MyConfig' Sequence='2' />

<!--Set New Value-->
<util:XmlFile Id='XmlSettings3' File='[#app.config]' Action='setValue' 
              Name='Server' Value='Pusevov' ElementPath='//configuration/MyConfig' Sequence='3' />

<!--Update Existing Value, Existing Element-->
<util:XmlFile Id='XmlSettings4' File='[#app.config]'
  Action='setValue' Name='newVersion' Value='7.7.7' ElementPath='//configuration/ExistingConfig/bindingRedirect' Sequence='4' />

</Component>

I hope that makes some kind of sense. Like I said, I find this fiddly and error prone at times, but so are other tools for this kind of updates. Remember to try first with a primitive test case and do test installs to test for runtime errors. Make something small that works and then build on it - which is obviously self-evident, but it is tempting to try it all in one go. "Fire in the hole, seek cover!".

Some links for safekeeping: