Reboot on install, Don't reboot on uninstall

2019-01-09 17:13发布

问题:

We have an installer which requires a reboot on install, but it is also rebooting on uninstall. Is there a way we can prevent the reboot when uninstalling?

This is what we have at the moment:

<InstallExecuteSequence>
  <ScheduleReboot After="InstallFinalize"/>
</InstallExecuteSequence>

Many thanks in advance!

回答1:

Add Condition to ScheduleReboot

You need to insert a condition for your ScheduleReboot entry along the lines of what is described here: https://www.firegiant.com/wix/tutorial/events-and-actions/extra-actions/ (the linked article may show a condition that is a little too inclusive or unrestricted).


UPDATE: There are some issues to consider:

  1. Undesired action: ScheduleReboot should never be used unless it is really necessary. For example, if you are trying to replace files that are in use MSI will handle that without a call to ScheduleReboot.

  2. Many installation modes: Without a proper condition, the ScheduleReboot will cause a reboot prompt to show up in many installation modes: install, uninstall, upgrade, repair, self-repair, patching, etc... This is not desirable.

  3. Silent, instant reboot: If an MSI is run in silent mode and REBOOT=ReallySuppress is not specified, a ScheduleReboot action will automatically trigger an instant reboot of the computer in question - which might be very surprising and very undesirable.


For your purpose, you can perhaps use a condition along these lines:

<InstallExecuteSequence>
    <ScheduleReboot After='InstallFinalize'>NOT Installed AND NOT WIX_UPGRADE_DETECTED</ScheduleReboot>
</InstallExecuteSequence>

It all depends on whether you want to schedule a reboot during a major upgrade, or just during the original, fresh installation? There is no way to tell without more information. A more run-of-the-mill condition like NOT Installed AND NOT REMOVE~="ALL" would appear to schedule a reboot during a major upgrade, but not for a manual uninstall not triggered by a major upgrade (I will test when I get a chance - UPDATE: verified, basic testing only).

Note that the special WIX_UPGRADE_DETECTED property is a WiX-specific construct that may only be set if you use WiX's MajorUpgrade element. You can also set up major upgrades the old fashioned way in WiX and avoid the MajorUpgrade element "convenience feature" which allows easier configuration of the major upgrade with fewer options - "auto-magic". I didn't verify if WIX_UPGRADE_DETECTED is still set using this "old school" major upgrade configuration.

You can also use the ActionProperty from the Upgrade table to detect that a major upgrade is "about to happen" (see this answer for a sample). This should work even for non-WiX MSI setups - and as such should be an alternative to WIX_UPGRADE_DETECTED (I believe this property is set after FindRelatedProducts has run).


WIX_UPGRADE_DETECTED vs UPGRADINGPRODUCTCODE

The MSI package being uninstalled during a major upgrade will have the special property UPGRADINGPRODUCTCODE set (which will not be set in the MSI being installed during the upgrade). This is a built-in MSI property, and not a WiX-specific construct. In other words, during a major upgrade - which is an uninstall of an old version and an install of a new version - the MSI being uninstalled will have the property UPGRADINGPRODUCTCODE set whilst the MSI being installed will have the property WIX_UPGRADE_DETECTED set (I will verify this shortly). It will also have the ActionProperty from the Upgrade table set after the standard action FindRelatedProducts has run.

If this sounds complicated, then I am afraid it is. This is a key problem with Windows Installer (despite the technology's major corporate benefits) - that basic, key operations - such as upgrades - are sometimes very complicated to get right. There may be some violations of the principle of least astonishment. There is good and bad in all technologies - obviously.


Special Considerations

Note that a reboot may be initiated regardless of whether the ScheduleReboot action is suppressed or not (for example if there are files that could not be replaced - or worse: a custom action forces a reboot via code - which is always wrong, a reboot should be scheduled not forced via code).

You can suppresses certain prompts for a restart of the system by using the REBOOT property (something you will have read already). More on System Reboots.


MSI Conditions

MSI conditions can be very tricky to get right. Get it wrong and your action runs unexpectedly during the wrong installation mode - or it doesn't run at all when it should. This is much easier to get wrong than what you might think - even with experience. The proof is in the pudding here, real-life testing. Here are some sample, complex conditions as an example: Wix Tools update uses old custom actions (just in case it is interesting).

There are many installation modes you should test in when you try to use complex conditions (or any condition for that matter): 1. fresh install, 2. repair, 3. modify, 4. self-repair, 5. patching, 6. uninstall, 7. major upgrade invoked uninstall, etc... There are also a few weird modes like resumed suspended installs featuring the RESUME property, and the AFTERREBOOT property relating to the ForceReboot action etc... Things one should keep in mind that are rarely tested.

Here are two "cheat-sheets" for conditioning:

  • Installshield condition cheat sheet.
  • How to add a WiX custom action that happens only on uninstall (via MSI)?

I have not had the time to go through all these conditions and test them, but the latter table looks reasonable at face value. However: I believe REMOVE can sometimes be set during installation (and during change). It is very complicated to deal with all permutations of possibilities since MSI's command line interface and property configuration is so flexible. Installed is also not set for the new MSI version being installed as part of a major upgrade, but it will be set for the MSI version being uninstalled - very confusing.

The Installshield cheat sheet I have never actively used or checked, but I find their suggestions for repair interesting to say the least - there are different entries depending on how the repair is invoked.

Please remember to also check self-repair - just delete the main application EXE and trigger self-repair by then invoking the application's advertised shortcut (if any). It has been years since I checked, but self-repair may only run actions between InstallInitialize and InstallFinalize. You don't want to schedule a reboot during a self-repair.