如何在MSI WIX修改安装中重写Ini文件组件(排除卸载场景)
MSI修改场景下强制Ini组件重新部署的解决方案
问题描述
我有一个包含Ini文件的常规组件,代码如下:
<Feature Id="F.my_ini_feature" Level="1" Display="hidden"> <ComponentRef Id="C.my_ini"/> </Feature> <Component Id="C.my_ini" Guid='my_guid' Directory='PRODUCT_BIN' Feature='Complete' > <CreateFolder/> <IniFile Id="ConfigFileLocal1" Action="addLine" Directory="PRODUCT_BIN" Name="start.ini" Section="ENVIRONS" Key="MyEnv" Value="[new_var]" /> </Component>
该文件在安装时创建,卸载时删除。但由于new_var的值会变化,我需要在修改安装时重写该文件,如何强制MSI安装程序在修改场景下重新部署此组件?
我已尝试如下设置REINSTALL属性,效果较好:
<SetProperty Sequence="ui" Before="ExecuteAction" Id="REINSTALL" Value="F.my_ini_feature,[REINSTALL]"> _CHANGE </SetProperty>
但存在一个场景无法解决:当用户进入程序和功能界面点击“更改”后选择卸载,此时仍处于_CHANGE状态,无法检测到卸载操作。
我也尝试在执行序列中基于功能状态设置REINSTALL,但失败了,似乎MSI不会重新读取REINSTALL的内容:
<SetProperty Sequence="execute" Before="ProcessComponents" Id="REINSTALL" Value="F.make_start_env_local,[REINSTALL]"> <![CDATA[!F.F.my_ini_feature= 3 AND &F.F.my_ini_feature <> 2]]> </SetProperty>
请问除真正卸载场景外,是否有更好的方法强制组件重新安装?
可行解决方案
1. 排除卸载场景的REINSTALL设置
修改UI序列的SetProperty条件,加入REMOVE <> "ALL"判断,排除用户通过“更改”入口选择完全卸载的场景:
<SetProperty Sequence="ui" Before="ExecuteAction" Id="REINSTALL" Value="F.my_ini_feature,[REINSTALL]"> _CHANGE AND REMOVE <> "ALL" </SetProperty>
当用户触发完全卸载时,REMOVE属性会被设为"ALL",此时条件不成立,不会执行组件重新安装操作。
2. 永久组件+自定义卸载清理
将组件标记为Permanent="yes",MSI会在每次修改安装时重新部署该组件(不会因文件已存在而跳过),同时通过自定义操作在完全卸载时删除Ini文件:
<Component Id="C.my_ini" Guid='my_guid' Directory='PRODUCT_BIN' Feature='Complete' Permanent="yes"> <CreateFolder/> <IniFile Id="ConfigFileLocal1" Action="addLine" Directory="PRODUCT_BIN" Name="start.ini" Section="ENVIRONS" Key="MyEnv" Value="[new_var]" /> </Component>
添加自定义操作处理卸载时的文件删除:
<CustomAction Id="DeleteIniOnUninstall" Directory="PRODUCT_BIN" ExeCommand="cmd /c del start.ini" Execute="deferred" Impersonate="no"/> <InstallExecuteSequence> <Custom Action="DeleteIniOnUninstall" Before="RemoveFiles">REMOVE="ALL"</Custom> </InstallExecuteSequence>
3. 配合REINSTALLMODE增强覆盖
搭配REINSTALL属性设置REINSTALLMODE,强制MSI覆盖现有文件并更新相关组件状态:
<SetProperty Sequence="ui" Before="ExecuteAction" Id="REINSTALLMODE" Value="amus"> _CHANGE AND REMOVE <> "ALL" </SetProperty>
REINSTALLMODE参数说明:
a:强制覆盖已安装的文件m:重新注册组件u:更新注册表项s:覆盖系统文件
可根据实际需求调整参数组合。
4. 修正执行序列的功能状态判断
之前的执行序列设置失败是因为条件表达式格式错误,修正后基于功能当前状态和请求状态判断,同时排除卸载场景:
<SetProperty Sequence="execute" Before="ProcessComponents" Id="REINSTALL" Value="F.my_ini_feature,[REINSTALL]"> <![CDATA[&F.my_ini_feature = 3 AND !F.my_ini_feature <> 2 AND REMOVE <> "ALL"]]> </SetProperty>
其中:
&F.my_ini_feature = 3:组件当前处于已安装状态!F.my_ini_feature <> 2:组件请求状态不是卸载REMOVE <> "ALL":排除完全卸载场景
内容的提问来源于stack exchange,提问作者Markus
相关产品推荐
相关产品推荐

