如何在用户取消选择特定Feature时执行自定义操作?
需求:用户取消选择特定Feature时执行自定义操作
要求在用户取消选择MyFeature时执行自定义Custom Action,无论当前操作是Repair、Upgrade还是Uninstall;但Upgrade过程中如果Feature被重新安装,则不执行该操作。
之前的尝试及问题
我曾尝试定义_UNINSTALLONLY属性来限制仅在卸载时执行:
<SetProperty Id="_UNINSTALLONLY" After="FindRelatedProducts" Value="1"> <![CDATA[Installed AND NOT UPGRADINGPRODUCTCODE]]></SetProperty>
并在InstallExecuteSequence中添加延迟执行的CustomAction:
<Custom Action="HandleMyFeatureMyCustomActionOnUnselect" Before="InstallFinalize"> <![CDATA[_UNINSTALLONLY AND (!MyFeature >= 2) AND (&MyFeature <= 2) ]]></Custom>
该方案在多数场景有效,但Upgrade过程中用户取消选择Feature时,操作不会被触发。
还尝试过其他条件,均存在问题:
(!MyFeature >= 2) AND (&MyFeature <= 2):Upgrade时,即使用户未更改选择也会触发操作_UNINSTALLONLY AND (&MyFeature <= 2):Upgrade时取消选择其他Feature2也会触发操作
已实现功能及代码上下文
目前已实现升级时可靠移除旧版本、根据当前状态预选Feature的需求,相关代码如下:
CustomAction定义
<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>
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>
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>
解决方案
要实现仅当用户将MyFeature从已选择改为未选择时执行自定义操作,需调整CustomAction的执行条件,覆盖所有目标场景并排除误触发情况:
调整CustomAction执行条件
替换原有的CustomAction触发条件,使用以下组合逻辑:
<Custom Action="SetHandleMyFeatureMyCustomActionOnUnselectPropertyValues" Before="HandleMyFeatureMyCustomActionOnUnselect" > <![CDATA[(!MyFeature >= 3) AND (&MyFeature <= 2) AND NOT REINSTALL~="MyFeature"]]> </Custom> <Custom Action="HandleMyFeatureMyCustomActionOnUnselect" Before="InstallFinalize"> <![CDATA[(!MyFeature >= 3) AND (&MyFeature <= 2) AND NOT REINSTALL~="MyFeature"]]> </Custom>
逻辑说明
!MyFeature >=3:表示MyFeature在操作前处于已安装状态(Windows Installer中,Feature已安装对应的状态值为3)&MyFeature <=2:表示MyFeature的目标状态为未安装NOT REINSTALL~="MyFeature":排除Upgrade或Repair过程中重新安装该Feature的场景,避免误触发
内容的提问来源于stack exchange,提问作者gReX
相关产品推荐
相关产品推荐

