Wix Tools update uses old custom actions

后端 未结 2 1214
星月不相逢
星月不相逢 2020-11-28 16:59

we\'ve discovered some strange behavior using WIX Setup Tools. We have deployed some major versions (2.2.0 - to 2.2.4). For 2.2.5 we changed a small things in custom action

相关标签:
2条回答
  • 2020-11-28 17:36

    You should be more specific about what you mean by "update" because it could be a patch, minor upgrade, major upgrade. If it's a major upgrade you should say where it's sequenced. However there are two general reasons why custom actions from a previous version might run:

    1. Brian's comment/answer - they were conditioned incorrectly in that original install, and when the update goes through the sequences in the older install it finds that the condition evaluates true. If you like, there are no such things as install custom actions or uninstall custom actions: there are only custom actions with conditions. In the WiX source that was posted as an update, the use of UPGRADINGPRODUCTCODE is not correct. This property is set in the older product when it is being uninstalled during a major upgrade, so any condition in the old install that says "or UPGRADINGPRODUCTCODE" will be true. If you want a condition that is set in the upgrade install when it is upgrading an older produce then use WIX_UPGRADE_DETECTED, as used by the MajorUpgrade element.

    2. The act of doing an update has caused a repair of the older product and therefore it has run the custom actions, and they might even have a correct condition. If, for example, a binary file has been replaced and is a candidate for replacement during your update, then Windows Installer will repair and restore the binary that doesn't match so it can decide whether to install the one from the update. This will reinstall the feature containing that binary. Custom actions conditioned on feature or component install could therefore run.

    Also, to extend Stein's answer, Windows Installer and WiX have a move (see the CopyFile element). And why install a file to one location and immediately move it to another location? I assume there's a reason for not simply installing it and the final location without doing a move?

    0 讨论(0)
  • 2020-11-28 17:44

    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...
    0 讨论(0)
提交回复
热议问题