Calum MacLeod
Calum MacLeod

Reputation: 443

Optionally leave old version of component on upgrade

I've been trying to set up a WiX component such that the user can specify that the installer should not upgrade that component on a MajorUpgrade. I had the following code, but this means that if the condition is met then the new version is not installed, but the old version is also removed.

<Component Id="ExampleComponent" GUID="{GUID here}">
  <Condition>NOT(KEEPOLDFILE="TRUE")</Condition>
  <File Id="ExampleFile" Name="File.txt" KeyPath="yes" Source="File.txt"/>
</Component>

Ideally, if the user specifies "KEEPOLDFILE=TRUE", then the existing version of "File.txt" should be kept. I've looked into using the Permanent attribute, but this doesn't look relevant.

Is this possible to achieve without using CustomActions?

Upvotes: 0

Views: 743

Answers (2)

Stein &#197;smul
Stein &#197;smul

Reputation: 42136

I tried to make this a comment, it became to long. I prefer option 4 that Phil describes. Data files should not be meddled with by the setup, but managed by your application exe (if there is one) during its launch sequence. I don't know about others, but I feel like a broken record repeating this advice, but hear us out...

There is a description of a way to manage your data file's overwriting or preservation here. Essentially you update your exe to be "aware" of how your data file should be managed - if it should be preserved or overwritten, and you can change this behavior per version of your application exe if you like. The linked thread describes registry keys, but the concept can be used for files as well.


So essentially:

  1. Template: Install your file per-machine as a read-only template
  2. Launch Sequence: Copy it in place with application.exe launch sequence magic
  3. Complex File Revision: Update the logic for file overwrite or preservation for every release as you see fit along the lines as the linked thread proposes

Your setup will "never know" about your data file, only the template file. It will leave your data file alone in all cases. Only the template file it will deal with.


Liberating your data files from the setup has many advantages:

  1. Setup.exe bugs: No unintended accidental file overwrites or file reset problems from problematic major upgrade etc... this is a very common problem with MSI.
  • Setup bugs are hard to reproduce and debug since the conditions found on the target systems can generally not be replicated and debugging involves a lot of unusual technical complexity.
  • This is not great - it is messy - but here is a list of common MSI problems: How do I avoid common design flaws in my WiX / MSI deployment solution? - "a best effort in the interest of helping sort of thing". Let's be honest, it is a mess, but maybe it is helpful.
  1. Application.exe Bugs: Keep in mind that you can make new bugs in your application.exe file, so you can still see errors - obviously. Bad ones too - if you are not careful - but you can easily implement a backup feature as well - one that always runs in a predictable context.
  • You avoid the complicated sequencing, conditioning and impersonation concerns that make custom actions and modern setups so complicated to do right and make reliable.
  • Following from that and other, technical and practical reasons: it is much easier to debug problems in the application launch sequence than bugs in your setup.
    • You can easily set up test conditions and test them interactively. In other words you can re-create problem conditions easily and test them in seconds. It could take you hours to do so with a setup.
    • Error messages can be interactive and meaningful and be shown to the user.
    • QA people are more familiar with testing application functionality than setup functionality.
    • And I repeat it: you are always in the same impersonation context (user context) and you have no installation sequence to worry about.

Upvotes: 0

PhilDW
PhilDW

Reputation: 20780

A bit more background information would be useful, however:

  1. If your major upgrade is sequenced early (e.g. afterInstallInitialize) the upgrade is an uninstall followed by a fresh install, so saving the file is a tricky proposition because you'd save it, then do the new install, then restore it.

  2. If the upgrade is late, then file overwrite rules apply during the upgrade, therefore it won't be replaced anyway. You'd need to do something such as make the creation and modify timestamps identical so that Windows will overwrite it with the new one. The solution in this case would be to run a custom action conditioned on "keep old file", so you'd do the reverse of this:

https://blogs.msdn.microsoft.com/astebner/2013/05/23/updating-the-last-modified-time-to-prevent-windows-installer-from-updating-an-unversioned-file/

And it's also not clear if that file is ALWAYS updated, so if in fact it has not been updated then why bother to ask the client whether to keep it?

  1. It might be simpler to ignore the Windows Installer behavior by setting its component id to null, as documented here:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa368007(v=vs.85).aspx

Then you can do what you want with the file. If you've already installed it with a component guid it's too late for this solution.

  1. There are better solutions that require the app to get involved where you install a template version of this file. The app makes a copy of it that it always uses. At upgrade time that template file is always replaced, and when the app first runs after the upgrade it asks whether to use the new file (so it copies and overwrites the one it was using) or continue to use the existing file. In my opinion delegating these issues to the install is not often an optimal solution.

Setting attributes like Permanent is typically not a good idea because they are not project attributes you can turn on and off on a whim - they apply to that component id on the system, and permanent means permanent.

Upvotes: 1

Related Questions