wixwindows-installercustom-actionwix3

How to execute a custom action when a user changes a feature from 'selected' to 'unselected'?


I want to execute my Custom Action if user is unselecting a specific feature. It doesn't matter if this is during a Repair, Upgrade or Uninstall. The action should not be executed, when during a Upgrade the feature is reinstalled.

With my research: Action-Conditions, Conditional Statement Syntax, Property-Table, _UPGRADE Property, execute an action only on Uninstall, neither on repair, nor upgrade nor install

I come to this solution:

_UNINSTALLONLY Property, that help to execute the Custom Action only on uninstall:

<SetProperty Id="_UNINSTALLONLY" After="FindRelatedProducts" Value="1">
       <![CDATA[Installed AND NOT UPGRADINGPRODUCTCODE]]></SetProperty>

And my deferred CustomAction inside my InstallExecuteSequence:

<Custom Action="HandleMyFeatureMyCustomActionOnUnselect" Before="InstallFinalize">
  <![CDATA[_UNINSTALLONLY AND (!MyFeature >= 2) AND (&MyFeature <= 2) ]]></Custom>

This works, expect when User is unselecting feature on upgrade. Then the action is not called.

I tried:

(!MyFeature >= 2) AND (&MyFeature <= 2): Problem: Action is called on upgrade, even User doesn't change selection

_UNINSTALLONLY AND (&MyFeature <= 2): Problem: Action is also called, when I unselect another Feature2 on Upgrade

Now I feel a little bit lost.

Another requirement is that, during a product upgrade, the old version is reliably removed. Additionally, it is important to preselect the features based on their current status in the setup. I have successfully achieved this. To rule out any interactions with my issue, here is some additional context:

<CustomAction Id="HandleMyFeatureMyCustomActionOnUnselect" BinaryKey="FeatureCustomActions"
    DllEntry="HandleMyFeatureMyCustomActionOnUnselect" Impersonate="no"  Execute="deferred"  
    Return="check" />

<CustomAction Id="SetHandleMyFeatureMyCustomActionOnUnselectPropertyValues" Property="HandleMyFeatureMyCustomActionOnUnselect" 
    Value="INSTALLFOLDER=[INSTALLFOLDER]" />    
    
<Property Id='INSTALLFEATURE'>
        <RegistrySearch Id='InstallFEATURE' Root='HKLM'
                        Key='SOFTWARE\Somewhere\AnotherKey'
                        Name='FEATUREINSTALLED' Type='raw' />
</Property>

The InstallExecuteSequence

<InstallExecuteSequence>
   <Custom Action="SetREINSTALL" Before="CostInitialize">
            Installed AND REMOVE ~= "" AND NOT REINSTALL
   </Custom>
   <RemoveExistingProducts After="InstallInitialize"/>
   ...
   <Custom Action="SetHandleMyFeatureMyCustomActionOnUnselectPropertyValues" Before="HandleMyFeatureMyCustomActionOnUnselect" ><![CDATA[_UNINSTALLONLY AND (!MyFeature >= 2) AND (&MyFeature <= 2) ]]></Custom>
   <Custom Action="HandleMyFeatureMyCustomActionOnUnselect" Before="InstallFinalize"><![CDATA[_UNINSTALLONLY AND (!MyFeature >= 2) AND (&MyFeature <= 2) ]]></Custom>
   ...
</InstallExecuteSequence>

The Features

<Feature Id="MyFeature" Title="My Feature" ConfigurableDirectory="INSTALLFOLDER"  Display="expand" Level="1">
    <Condition Level="2">INSTALLFEATURE=0</Condition> 
    <ComponentGroupRef Id="FEATURE"/>
</Feature>
<Feature Id="MyFeature2" Title="My Feature2" ConfigurableDirectory="INSTALLFOLDER"  Display="expand" Level="1">
    <Condition Level="2">INSTALLFEATURE2=0</Condition> 
    <ComponentGroupRef Id="FEATURE2"/>
</Feature>

So my question is:
How to execute a custom action when a user changes a feature from 'selected' to 'unselected'?


Solution

  • I solved it, with

    <SetProperty Id="_NEWINSTALLER" After="FindRelatedProducts" Value="1">
       <![CDATA[NOT UPGRADINGPRODUCTCODE]]></SetProperty>
    

    and the condition

    <Custom Action="SetHandleMyFeatureMyCustomActionOnUnselectPropertyValues" Before="HandleMyFeatureMyCustomActionOnUnselect" >
        <![CDATA[_NEWINSTALLER AND (!MyFeature >= 2) AND (&MyFeature <= 2) ]]></Custom>
    <Custom Action="HandleMyFeatureMyCustomActionOnUnselect" Before="InstallFinalize">
        <![CDATA[_NEWINSTALLER AND (!MyFeature >= 2) AND (&MyFeature <= 2) ]]>
    </Custom>
    

    I was so damn close! Now it's going through the test :-)