When testing the serviceability of your product before you ship, it’s important to test any conditions you might have on the product, features, components, and actions.
Feature conditions can set the install level of a feature when the package is installed. But as the Condition table documentation states, be sure that the condition does not evaluate to False at any time after the feature is installed. Once the feature is installed, the condition is used merely to inform Windows Installer whether it is installed or not. If Windows Installer does not think the feature is installed locally, is will not reinstall it or remove it during uninstall. This is also the problem when removing components from features, which leaves the feature state appearing as Advertised and is never reinstalled, patched, or removed again.
Component conditions are only evaluated when the component is first installed unless the component is marked as transitive. Unlike features, component conditions actually determine whether the component is installed or not whenever they are evaluated. So if the condition evaluates to Null or True the component is installed; otherwise, the component is removed. Transitive components are useful when the installed resources depend on the machine state which can change. Examples of changes are upgrading the operating system or installing some other feature or product. Transitive components can provide light-up features in response to such changes.
Conditions on both standard and custom actions determine whether the actions are executed.
Common mistakes with conditions
Mistake: If reinstallation (repairs) causes problems for applications, setup developers may condition the product or actions as: NOT REINSTALL.
The problem with denying reinstall is that patching is simply the act of applying transforms and reinstalling the product. If a patch updates existing features, those features are passed to the REINSTALL property. Rather than denying reinstall, it’s best to fix whatever problems prevent reinstall. Commonly, this might be because a custom action does something wrong. For example, if a custom action adds an element to an XML file every time it is run and only one element can exist, make sure the custom action always checks whether the element exists. Custom actions should be data driven and robust, just like standard actions. Never assume the machine state exactly matches the state Windows Installer assumes. In most cases, Windows Installer only considers the state for the current product – not any other products installed – nor is aware of any user modifications.
Mistake: To make sure that actions are not executed when the product is removed, setup developers may condition actions as: NOT REMOVE.
If a product has multiple features, features can be removed by passing them to the REMOVE property. When the product is uninstalled, REMOVE is set to “ALL”. Even if the full list of features is installed, Windows Installer sets REMOVE to “ALL” after the InstallValidate action. So if you do not want to run custom actions during product uninstall, use the condition: NOT REMOVE = “ALL”.
Mistake: To make sure components are only installed when certain properties are passed to the command line, setup developers may condition components when these properties are defined.
If the components are transitive, these properties must be patched every time. When they are not defined, the components are uninstalled. Even if the components are not transitive, if ever the parent features are uninstalled those components are uninstalled. When the feature is installed again, those properties must be specified or those components are not installed again. Those conditions are evaluated whenever the components are first installed.
Fixing bad custom actions
If you have shipped bad custom actions, you can often fix them in a patch. But be aware that even if you ship the fixed condition in every patch, when you uninstall the last patch the bad condition is used again. This is because patch uninstall is exactly the reverse of patch install: previously applied transforms are unapplied from the product, and the product is reinstalled. So because the transforms are missing, the fixed custom action is not used.
With WiX v3 patching using pyro.exe, you can change the condition but cannot refer to it directly in a PatchFamily. Instead, you need to refer to an element – such as a Component element using a ComponentRef – in the same fragment as the condition. The problem is, however, most times setup developers author conditions in the entry section – the main section that also contains the Product/@Version which becomes the ProductVersion property. So if you intend to ship a small update but increment the ProductVersion as part of the builds, you may end up shipping a minor upgrade which creates a new baseline; i.e., previous small updates may not apply, or fixes are effective removed if the minor upgrade patch is not cumulative.
You can add the Condition element in a fragment that is referenced in the upgrade product, but unless the old condition is also moved to the same section you’ll end up with both conditions when the patch is applied. This is because the Condition column itself in a LaunchCondition is the primary key. If you change the condition, you change the key and that’s what transforms use to determine whether a row is added, updated, or removed. Fortunately, WiX v3 patching lets you move elements to different fragments. You can move the Condition element for a product to a section being updated in a patch already, but you will have to rebuild both the target and upgrade packages. This also means you should have saved a complete layout of your target (baseline) product. You want it to build exactly as it shipped as a installer package or the patch may not apply or apply the wrong changes.
All this can typically be avoided if you test the serviceability of your product prior to shipping.