cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Kelter
Level 10

Using Feature States in Component condition

I have a couple of Components (Component1 and Component2) under FeatureB. (These two components contain only registry data, but that's probably not pertinent here.) Which one should be installed depends on the state of FeatureA, and VersionNT.

Therefore, the condition for Component1 is:
(VersionNT<600) OR (&FeatureA=3) OR ( (!FeatureA=3)AND(&FeatureA<>2) )
And the condition for Component2 is
NOT( (VersionNT<600) OR (&FeatureA=3) OR ((!FeatureA=3)AND(&FeatureA<>2)) )

The following are lines from the installation log:[CODE]INSTALLATION: FeatureA -> Local

MSI (s) (00:04) [10:38:22:338]: Feature: FeatureA; Installed: Absent; Request: Local; Action: Local

MSI (s) (00:04) [10:38:22:338]: Component: __FeatureA.exe65; Installed: Null; Request: Local; Action: Local
MSI (s) (7C:D0) [11:07:29:284]: Component: FeatureA.exe; Installed: Absent; Request: Local; Action: Local

MSI (s) (00:04) [10:38:22:338]: Component: __Component265; Installed: Null; Request: Local; Action: Local
MSI (s) (00:04) [10:38:22:354]: Component: Component2; Installed: Absent; Request: Local; Action: Local

MSI (s) (00:04) [10:38:22:338]: Component: __Component165; Installed: Null; Request: Local; Action: Null
MSI (s) (00:04) [10:38:22:354]: Component: Component1; Installed: Absent; Request: Local; Action: Null

MODIFY: FeatureA -> Absent

MSI (s) (68:8C) [12:39:01:030]: Feature: FeatureA; Installed: Local; Request: Absent; Action: Absent

MSI (s) (68:8C) [12:39:01:045]: Component: __FeatureA.exe65; Installed: Null; Request: Absent; Action: Absent
MSI (s) (68:8C) [12:39:01:045]: Component: FeatureA.exe; Installed: Local; Request: Absent; Action: Absent

MSI (s) (68:8C) [12:39:01:045]: Component: __Component165; Installed: Null; Request: Null; Action: Null
MSI (s) (68:8C) [12:39:01:045]: Component: Component1; Installed: Local; Request: Null; Action: Null

MSI (s) (68:8C) [12:39:01:045]: Component: __Component265; Installed: Null; Request: Null; Action: Null
MSI (s) (68:8C) [12:39:01:045]: Component: Component2; Installed: Local; Request: Null; Action: Null[/CODE]
Is it invalid to use feature states and feature actions in component conditions? Is there a better way to do what I'm doing? Did I make an obvious mistake and i'm just plain not seeing it?

Thanks in advance.
Labels (1)
0 Kudos
(9) Replies
Kelter
Level 10

Where do the "__[ComponentName]65" components come from?
0 Kudos
Not applicable

If a component requires a specific feature to be installed then it should be under that feature or a subfeature of that feature.

To be honest, you can't or shouldn't really use any feature or component conditions in any other feature or component.
0 Kudos
Kelter
Level 10

Thanks for your response, Mr. Wolf. You're typically right to the point with very specific answers, so without deprecating your response, I'd like to clarify the purpose of my question.

The question was "is it invalid" which is to say "Can I use a feature state in a component condition," so the subtle difference between whether I should or can is important. The two components belong to one feature, but which one of the of the two gets installed depends on whether or not another feature is to be installed.

It sounds like you're certian that we shouldn't but that there may be doubt as to whether we can, so I'd just like to open up the possibility that I may have done something asinine with my conditions.

The only alternative I see is to make a Custom Action to handle this, but you can imagine the maintenance concerns. I'd like to be as MSI as possible in handling this.
0 Kudos
Not applicable

I usually do try to get straight to the point. I feel like your time is important enough that I can respect it by just giving the straight & narrow. Plus I don't have a lot of time to address community posts, so by being brief I can answer more posts and (hopefully!) help more people 🙂

The Component Table's documentation does allow you to reference other Features specifically ( http://msdn2.microsoft.com/en-us/library/aa368007(VS.85).aspx 😞

Condition
This column contains a conditional statement that can control whether a component is installed. If the condition is null or evaluates to true, then the component is enabled. If the condition evaluates to False, then the component is disabled and is not installed.

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.

Note that unless the Transitive bit in the Attributes column is set for a component, the component remains enabled once installed even if the conditional statement in the Condition column later evaluates to False on a subsequent maintenance installation of the product.

The Condition column in the Component table accepts conditional expressions containing references to the installed states of features and components. For information on the syntax of conditional statements, see Conditional Statement Syntax.


So to answer your direct question, Yes this should work. However, your condition requires that the Transitive Bit be set for the component to be reevaluated during an uninstallation. So your direct question is simple, but the underlying assumed question is more complicated. Reliance on the transitive bits to make your installations work properly is typically asking for a maintenance nightmare. If your components don't have the transitive bits set then the conditions are not re-evaluated and they will not be scheduled to do anything.

But my point is that if ComponentX in FeatureB requires that FeatureA be installed then FeatureB should be a subfeature of FeatureA so that it will be automatically removed. Component Y can be in a different feature that is made mutually exclusive through installer logic - say a radio button on a dialog.

Obviously I'm oversimplifying for the purposes of this forum, but the time investment required to make that happen will easily defeat the sheer complexity and likely later (random) issues that happen after you've updated the product a few times or something of that nature when using transitive components.

Thus the need for these conditions is entirely mitigated and the support required for your product will be reduced.

Where do the "__[ComponentName]65" components come from?


Those are costing components used by Windows Installer. They aren't really important for much outside of internal engine operations.
0 Kudos
Kelter
Level 10

hmm..it should work, yet it doesn't, and it always seems to evaluate to true. Perhaps this is because in the documentation you indicated, it says
The Condition column in the Component table accepts conditional expressions containing references to the installed states of features and components.
but says nothing of accepting feature actions. After testing, I'll post my results.
But my point is that if ComponentX in FeatureB requires that FeatureA be installed then FeatureB should be a subfeature of FeatureA so that it will be automatically removed. Component Y can be in a different feature that is made mutually exclusive through installer logic - say a radio button on a dialog.

Here's the problem with that...Feature B Contains Components 1 and 2, which essentially set up file type associations. The 2 possible targets are always installed, but the one associated with our file extension varies based on whether the service in FeatureA is installed or not. To the end user, it should still appear as though FeatureA is it's own Feature.

I'll post a solution when I stumble upon it.
0 Kudos
Not applicable

Again, are your components marked transitive? What is the relationship between ComponentA & ComponentB to FeatureA? Are they beneath FeatureA? Are they in a different feature that is above or below FeatureA?

Presumably, this is not a full uninstallation. Is the feature associated with these components scheduled for uninstallation?

Component state management through conditions is complicated, so without the details it's impossible to really help.
0 Kudos
Kelter
Level 10

Features A and B are both root level features, although FeatureA could fall under FeatureB it woudln't solve the problem.
FeatureA
ComponentA1
FeatureB
ComponentX
ComponentY

is no different as far as our conversation is cocerned than

FeatureB
FeatureA
ComponentA1
ComponentX
ComponentY


I did take your advice and make the components in question transient. I think I'll have some luck using MsiSetComponentState. Although I can't apparently use feature actions in a component condition, I can use them in custom action conditions after the costfinalize action. I'll hopefully get to testing that logic today, and post the results.
0 Kudos
Not applicable

Well, if the Feature's Action is not decided prior to CostFinalize then you'd see that sort of behavior, but the execute sequence's CostFinalize should handle the component state properly.

Is this a maintenance operation? If so and if the components aren't marked transitive then their conditions are not re-evaluated. In the situation where you have:

FeatureA
--ComponentA

FeatureB
--ComponentB
--ComponentC

Where the states of components B & C are based on the state of ComponentA, during a maintenance operation (REINSTALL="ALL" after InstallValidate) ComponentB and ComponentC's state will not be changed from installed based on the condition.
0 Kudos
Kelter
Level 10

...i've discovered the following:

1. You cannot use Feature-States or Feature-Actions in Component conditions...despite what the documentation on the component table says.

2. You can use Feature-Actions and Feature-States in the condition field of a CA (scheduled after CostFinalize in any sequence.)

3. You can use Feature-Actions and Feature-States in the condition field of a component action.

4. Transient components (those with the msidbComponentAttributesTransitive bit set in its attributes...which is equivalent to setting the "Reevaluate Condition" property to "Yes" in the IS GUI) have their conditions reevaluated when the feature to which they belong is reinstalled.

Given this info, the solution (pattern?) that I've developed is as follows:

I'll stipulate that NewFeature1 is the feature containing the components with conditions that depend on the state of MainFeature. The components are named MainFeatureInstalled (which should be installed when the feature MainFeature is installed) and MainFeatureNotInstalled (which gets installed when the feature MainFeature is not installed.)
MainFeature
MainComponent
NewFeature1
MainFeatureInstalled
MainFeatureNotInstalled

1. Set a control event with the following settings on the "InstallNow" button of the ReadyToInstall Dialog:
Event: Reinstall
Argument: NewFeature1
Condition: (Installed) AND (!NewFeature1=3 AND &NewFeature1<>2)
(Perhaps you may need more comprehensive conditions but this is simple and sufficient for local-only installations...on that note, feel free to post improvements!)

2. Schedule Set-A-Property custom actions after CostFinalize in both sequences. In the UI sequence, this obviously needs to be after your dialogs. The following table describes these Set-A-Property CAs:
Property  Property
Name Value Condition
-------- -------- ---------
MFACTION 2 &MainFeature=2
MFACTION 3 &MainFeature=3
MFSTATE 2 !MainFeature=2
MFSTATE 3 !MainFeature=3


3. Assign conditions to the components.
Component
Name Condition
--------- ---------
MainFeatureInstalled MFACTION=3 OR ((MFSTATE=3) AND (MFACTION<>2))
MainFeatureNotInstalled NOT( MFACTION=3 OR ((MFSTATE=3) AND (MFACTION<>2)) )


4. Set the transitive bit on the components. This causes their conditions to be re-evaluated when their associated feature is reinstalled.

Well, if the Feature's Action is not decided prior to CostFinalize then you'd see that sort of behavior, but the execute sequence's CostFinalize should handle the component state properly.

This get's into a whole chicken/egg scenario. Here's the funny thing...costfinalize has to happen before the dialog sequence containing a SelectionTree control in order to properly display the features and states within said tree control. The problem is that the user's interaction with the is necessary before CostFinalize resolves the actions that need to take place.

I've worked around this creatively enough, so not to worry.
0 Kudos