When you include deferred custom actions – that somehow modify the machine – in your setup, you have two big responsibilities:
- Provide rollback custom actions that “undo” what the deferred CAs do so that the installation transaction is actually transactional.
OK, so numbers 2 through 4 are kinda the same but not really: Even a simple installation (say, without patching or upgrades) has three different scenarios you need to test when you have deferred/rollback custom actions:
- Installation rollback.
- Repair rollback.
- Uninstallation rollback.
- All of the above.
The right behavior for each kind of rollback is usually the opposite action. Rolling back installation is uninstallation. Rolling back uninstallation is installation. Rolling back repair is usually installation. Mixing installation, repair, and uninstallation is possible if your package has user-selectable features and users go into maintenance mode to turn on and off features. And, of course, it’s always an option from the msiexec.exe command line using the ADDLOCAL/ADDSOURCE/ADDDEFAULT, REMOVE, and REINSTALL properties.
Testing rollback means testing failure
Windows Installer initiates rollback when an action fails, so to test rollback you need to cause a failure. WiX includes an easy way to trigger failure: The WixFailWhenDeferred custom action, part of WixUtilExtension, triggers a failure when it’s executed. Include it in your package by referencing WixUtilExtension (in your Votive .wixproj or via the -ext switch to the light.exe command line) and adding a CustomActionRef to your package authoring:
<CustomActionRef Id="WixFailWhenDeferred" />
WixFailWhenDeferred automatically schedules itself in InstallExecuteSequence before InstallFinalize, with a condition of:
The condition means that you can have one package to test all the different possible combinations of “normal” installation and rollback. Just pass the WIXFAILWHENDEFERRED=1 property value on the msiexec.exe command line to trigger rollback. For example:
msiexec /qb- /i intermediate.msi /L*vx installfail.log WIXFAILWHENDEFERRED=1 msiexec /qb- /i intermediate.msi /L*vx install.log msiexec /qb- /fvamus intermediate.msi /L*vx repairfail.log WIXFAILWHENDEFERRED=1 msiexec /qb- /fvamus intermediate.msi /L*vx repair.log msiexec /qb- /x intermediate.msi /L*vx uninstallfail.log WIXFAILWHENDEFERRED=1 msiexec /qb- /x intermediate.msi /L*vx uninstall.log</p> </p>
WixFailWhenDeferred has been in WiX v3 weekly releases since April.