1

We use the wix 3.9 to create an msi for our product. Our Target: We want to deliver a config file (.txt-file) via the msi. When an config file already exists in the installation folder, the file should not be overwritten by an upgrade. Unfortunately, on an upgrade, Wix removes the configuration file.

The Product Element:

<Product Id="*" Name="$(var.AppName) V$(var.Version) $(var.TargetBuild)" Language="1033" Version="$(var.Version)" Manufacturer="$(var.Manufacturer)" UpgradeCode="$(var.UpgradeCode)">

The $(var.UpgradeCode) is static and will never be changed.

The Upgrade Tags:

<MajorUpgrade DowngradeErrorMessage="A newer version of $(var.AppName) is already installed." AllowSameVersionUpgrades="yes" />

<Upgrade Id="$(var.UpgradeCode)">
  <UpgradeVersion Minimum="1.0.0"
                  IncludeMinimum="yes"
                  OnlyDetect="yes"
                  Maximum="$(var.Version)"
                  IncludeMaximum="yes" 
                  Property="PREVIOUSVERSIONSINSTALLED" />
</Upgrade>

<Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />

Here is the config file:

<Component Id="ConfigComponent" NeverOverwrite="yes" Guid="GUID-HERE">
    <File Id="ConfigOutput" KeyPath="yes" Name="MyConfig.config" Source="MyConfig.config.bak"/>
</Component>

In Addition, I use RemoveFolderEx to remove generated files by the Application itself. But when I commented out this block, the problem still occurs. But I want to show the codeblock for the completeness:

<Component Id="RemoveAll" Guid="MYGUID">
    <RemoveFile Id="RemoveAllFilesOnUninstall" Directory="APPLICATIONFOLDER" Name="*.*" On="uninstall" />
    <RemoveFolder Id="RemoveAllFoldersOnUninstall" Directory="APPLICATIONFOLDER" On="uninstall" />

    <RegistryValue Root="HKLM" Key="SOFTWARE\$(var.Manufacturer)\$(var.AppName)" Name="Path" Type="string" Value="[APPLICATIONFOLDER]" KeyPath="yes" />
    <util:RemoveFolderEx On="uninstall" Property="APPLICATIONFOLDER" /> 
</Component>

Repro: At first, we install the Software and the file 'MyConfig.config' appears in the application folder as expected. After that, we make changes inside of this config file. At next, we build a second .msi and execute it. When the update is made, all files are overwritten as expected. But we are missing the file 'MyConfig.config' in the installation folder now.

UPDATE:

The attribute Permanent="yes" does also not work as expected. The config File is still removed on an upgrade:

<Component Id="ConfigComponent" Permanent="yes" NeverOverwrite="yes" Guid="GUID-HERE">
    <File Id="ConfigOutput" KeyPath="yes" Name="MyConfig.config" Source="MyConfig.config.bak"/>
</Component>
Simon
  • 4,157
  • 2
  • 46
  • 87

1 Answers1

2

What's happening during your Major Upgrade:

  1. The CostInitialize/CostFinalize actions determine what components in the new MSI should install. The ConfigComponent decides 'not' to install because it's marked as NeverOverwrite="yes".
  2. The old MSI is removed during the RemoveExistingProducts action. The previous config file is removed.
  3. The new MSI is installed. The ConfigComponent does not get installed based on the check from step 1.

A quick solution (although I'm sure there are better approaches out there):

Going forward, mark your ConfigComponent with Permanent="yes" so that MSI never removes it. You'll need to add a custom action that removes the file, and condition it on "$ConfigComponent=2 And Not UPGRADINGPRODUCTCODE" so that it only executes when the component is set to be deleted through a modify or full-uninstall, but not an upgrade.

If your MSI is already shipped to the world and you need to fix the upgrade scenario you'll need to write a custom action that copies the config file to a backup location before the old MSI removes it. Then another custom action to copy the config file back into the correct directory.

jbudreau
  • 1,287
  • 1
  • 10
  • 22
  • Looks like this is a issue with Windows Installer itself, read this link: https://community.flexerasoftware.com/showthread.php?96157-The-truth-the-whole-truth-about-quot-Never-overwrite-quot-and-quot-Permanent-quot-files – Isaiah4110 Apr 04 '16 at 16:10
  • Correct, this missing-files-after-upgrade issue is due to the way RemoveExistingProducts is scheduled. If REP is moved to right before InstallFinalize, then this problem goes away, but other considerations are needed for that change - https://msdn.microsoft.com/en-us/library/windows/desktop/aa371197%28v=vs.85%29.aspx – jbudreau Apr 04 '16 at 18:18
  • @jbudreau: Regarding your step 2: Why should the msi remove the previous config file? The previous installation also contains the attribute NeverOverwrite="yes". Therefor I expect, that the config file will not be removed. – Simon Apr 05 '16 at 05:30
  • @jbudreau: Your suggestion to user Permanent="yes" does not solve the problem. With that, the config file will be overwritten by the new config file of the upgrade. But the upgrade should not overwrite the old config file. The old config file should stay. – Simon Apr 05 '16 at 05:48
  • @jbudreau: When we use both, Permanent="yes" and NeverOverwrite="yes", then the config file will be still removed after an upgrade. – Simon Apr 05 '16 at 05:57
  • @jbudreau: now it works: When we use both, Permanent="yes" and NeverOverwrite="yes" and remove the entire component block Id="RemoveAll", then it seem to work. – Simon Apr 05 '16 at 07:30