Skip to Content

Feature states in component conditions

MSI has some funky syntax to support checking the action state (what MSI is planning to do during the current install transaction) and install state (what MSI already did, in a previous install transaction) of both features and components. See Conditional Statement Syntax for the details and Examples of Conditional Statement Syntax for some examples. (As an aside, would it have been too much to ask to avoid the Perl-like prefix characters and have something function-like such as FeatureActionState(featureId)?)

A couple of people on the wix-users mailing list have asked about using the feature action state in component conditions. There’s good news and bad news.

Good news for simple cases

The good news is that in simple cases with simple conditions, there’s probably another way to get the behavior you’re looking for. For example, one component can be assigned to multiple features, so if you’re trying to install a component when any of several features are being installed, just reference the component in all the features. MSI will install the component once, regardless of how many features reference it.

The bad news

If you want to conditionalize a component based on whether a particular feature is being installed (i.e., its action state), you can’t rely solely on the component’s condition. The Component Table doc has this to say:

The Condition field enables or disables a component only during the CostFinalize action. To enable or disable a component after CostFinalize, you must use a custom action or the DoAction ControlEvent to call MsiSetComponentState.

The CostFinalize action doc says:

The CostFinalize action queries the Condition table to determine which features are scheduled to be installed. Costing is done for each component in the Component table.

Unfortunately, it doesn’t state explicitly that the order of the two sentences is the order of execution. But, even if it did, there’s this table in Conditional Statement Syntax:

Feature and Component State Values

The following table shows where it is valid to use the feature and component operator symbols.

Operator Where this syntax is valid
$component-action In the Condition table, and in the sequence tables, after the CostFinalize action.
&feature-action In the Condition table, and in the sequence tables, after the CostFinalize action.
!feature-state In the Condition table, and in the sequence tables, after the CostFinalize action.
?component-state In the Condition table, and in the sequence tables, after the CostFinalize action.

So there are two fairly explicit strikes against being able to use a feature action state in a component condition:

  • Conditional Statement Syntax doesn’t list the Component table as a valid place to use the &feature-action syntax.
  • It says the syntax is valid only after CostFinalize but according to Component Table, that’s too late to use the component condition to enable/disable the component.

The Component Table says to use a “custom action or the DoAction ControlEvent to call MsiSetComponentState.” I haven’t quite deciphered whether the doc is saying to use DoAction to call a custom action from the UI or whether there’s a special, secret way of calling MsiSetComponentState via DoAction. If it’s the latter, I’m not aware of it (hence “special, secret”).

Here be dragons

Having been a writer for many years, I try to be nice about doc that is correct, even if in retrospect it’s not as helpful as it could have been. So here’s me being nice. The following sentence from Component Table easily leads a trusting reader down the wrong path:

The Condition column in the Component table accepts conditional expressions containing references to the installed states of features and components.

So here we have a sentence that contradicts the table in Conditional Statement Syntax and it’s really easy to misread the “installed state[s]” as “action states.” At the very least, it deserves clarification.