Wix Tools update uses old custom actions

Testing the Conditions

Condition #1:

Installed AND (NOT REMOVE="ALL" OR UPGRADINGPRODUCTCODE)

This rather odd constellation of conditioning will cause the custom action in question to not run during a fresh install, nor a manual uninstall. It seems this custom action will run during: major upgrade (which is a special type of uninstall), modify and repair. I suppose this would do the job of backing up the settings file. However…

During a major upgrade this would indeed look like the old custom action is being run, because what is running is your old package in major upgrade mode (which is a special type of uninstall) – hence featuring the old package’s custom actions (what is running is the old, cached database from your previous install – it uninstalls itself as part of the major upgrade). These custom actions never ran during the package’s initial install. But your other custom action to copy from temp will. That is probably not correct behavior.

To summarize:

  • Runs: major upgrade (run via the old MSI that uninstalls, but not in the new MSI), modify, repair
  • Does not run: first time install, uninstall.

Condition #2:

NOT Installed OR Installed AND (NOT REMOVE="ALL" OR UPGRADINGPRODUCTCODE)

The second condition, which is also a little exotic, seems to run on a fresh install and a major upgrade only. You probably only need it to run during major upgrade, but shouldn’t you also run during repair and modify? (these modes can also overwrite the settings file in certain cases, such as when REINSTALLMODE is set to “amus” to force overwrite files).

To summarize:

  • Runs: first time install, major upgrade
  • Does not run: uninstall, modify, repair

Standard Conditions

I don’t really have a full grasp of your whole scenario, but you can find a couple of links to resources to find common conditions here: Is it possible to run a custom action only in repair mode. I assume you want to back up the settings file on major upgrade, repair and modify to avoid it being overwritten. It looks like the conditions should be modified somewhat to achieve this?

I would recommend avoiding custom actions altogether, and below is a suggested approaches to achieve this.


Using The Application to Manage Settings Files

The management and setup of settings files has always been a difficult issue for deployment. I wrote up a short summary of different ways to deal with user settings files a few days ago: Create folder and file on Current user profile, from Admin Profile (it is a little reference of different ways to deploy settings files – recommended, and please let me know if it is unclear).

As can be seen in the linked answer above, it is often a good idea to use your application to initialize settings files from template copies that are installed by your setup to a read-only location in INSTALLDIR. You would then leave the template unchanged, but on launch your application copies your template settings file to each user’s user profile, or it just creates a copy in INSTALLDIR that the install process never will touch (you would need to apply ACL permissioning to make this settings file writeable by all users – not great design, but it does work). This template-based approach de-couples the settings file from deployment considerations. It will never be reset, uninstalled or meddled with from now on, since it was never installed by the setup. In fact you have to implement its cleanup or uninstall specifically (for example via a RemoveFolder / RemoveFile construct), or it will remain on disk on uninstall – which can also be a problem.

It is always an advantage to avoid Windows Installer’s complex architecture for dealing with custom actions. There is complex impersonation, complex conditioning, complex sequencing and also runtime dependencies for various binaries you call. Are you using DTF or just a straight C# assembly to call? There are some problems with the use of managed custom actions (wrong CLR version loaded, no .NET installed at all (locked?), dependencies on files in the GAC, etc… I don’t have a full overview – I stay away from all managed code for MSI deployment for these reasons).

When copying template settings files to a new file that is untouchable by your installer you will not have to deal with MSI’s whims and quirks – or any managed custom actions and their runtime requirements.


UPDATE: I remove the transitive approach I added earlier after further testing revealed it will only work in certain cases. I will check it again using minor upgrade instead of major upgrade. You could then use a minor upgrade patch to migrate all old version to set the settings file permanent so it is never uninstalled again, and then you would apply your major upgrade. This should be possible to wrap in a Burn bootstrapper.

UPDATE: as assumed (and verified) a minor upgrade can switch any component to permanent and there is no need to use any transitive settings for the component (I did not check if a minor update can switch a component to be non-permanent if it was set permanent before). In fact enabling transitive could actually uninstall the component if any condition attached to the component evaluates to false during the installation – I did not verify this, but it makes logical sense that it could be possible. The first thing that comes to mind is whether this could uninstall a component set to permanent. It shouldn’t, but I have seen such weirdness before with MSI. I can picture this necessary for a component set permanent deployed to System32 for example. In conclusion: if all you need is to preserve a settings file, just use a minor upgrade to set it permanent and then you can use major upgrades again. Don’t set the component transitive.

Just to mention it: your settings file is in fact not being overwritten by your current upgrade scheme by the way. It is being uninstalled and reinstalled during the major upgrade because its component was not originally set to Permanent = "yes" and NeverOverwrite="yes". This appears to have reverted it to the default values, but it was never overwritten. Rather it was uninstalled and reinstalled wiping out changes. MSI will not overwrite changed, non-versioned files, but it will happily uninstall and reinstall them unless they are marked permanent. It is a technology anti-pattern in my opinion – a lot of teams face this problem all the time. Hence my suggestion to review some data file deployment options as described here: Create folder and file on Current user profile, from Admin Profile (same link as above).

I hope some of this helps, and please let us know what you find during testing.


OLD ANSWER:

Brian’s mentioned the real advice, but maybe some questions for clarification. I will evolve this into an attempted answer once I have some answers.

  • How are these custom actions running? Are they EXE commands or are you running a launcher EXE which then invokes them? If you use such a launcher EXE, is it native (C++) or .NET? (C#/VB.NET). If it is .NET that’s often bad news.
  • Can we ask what you are doing with these copy commands? Could this be done in the application itself more reliably? This is perhaps the most common advice we give to people, that if followed can actually drastically simplify deployment and make it more reliable. You have more control of what happens in an application, you run in a predictable security context and there is no conditioning or sequencing to take care of. And finally: you can restart the application and do it again, a setup is “one shot”.
  • I will leave it at that for now…

Leave a Comment