如何防止空的Run注册表项被MSI引擎自动删除?
Wix Toolset v3卸载时保留Run注册表项的解决办法
问题场景
用Wix v3给HKLM\Software\Microsoft\Windows\CurrentVersion\Run添加启动项,卸载时自定义值被移除后,MSI会把空的Run项一并删除。按微软建议添加名称为"+"的虚拟值时,Wix报错;按错误提示使用RegistryKey/@action='createKey'也没能阻止Run项被删除。
有效解决方案
方案1:添加永久虚拟值
创建一个单独的永久组件,在Run项中添加一个非特殊名称的虚拟值,卸载时这个值会保留,确保Run项始终不为空:
<!-- 业务启动项组件(卸载时移除) --> <Component Id="AppRunEntry" Guid="你的GUID" Directory="INSTALLDIR"> <RegistryKey Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\Run"> <RegistryValue Name="YourApp" Value="[INSTALLDIR]YourApp.exe" Type="string" KeyPath="yes" /> </RegistryKey> </Component> <!-- 永久组件(卸载时保留虚拟值) --> <Component Id="KeepRunKey" Guid="另一个GUID" Directory="INSTALLDIR" Permanent="yes"> <RegistryKey Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\Run"> <RegistryValue Name="_KeepRun" Value="" Type="string" KeyPath="yes" /> </RegistryKey> </Component>
- 永久组件的
Permanent="yes"属性会让MSI在卸载时跳过它,虚拟值一直留在Run项里,避免项被删除。
方案2:自定义操作兜底(进阶)
如果方案1不符合需求,可通过自定义操作在卸载前检查Run项状态,自动补加临时值:
- 编写自定义DLL/VBS脚本,逻辑为:卸载时检查Run项内的现有值,若只剩你的业务值,就添加一个临时虚拟值。
- 在Wix中注册这个自定义操作,让它在注册表值移除前执行:
<CustomAction Id="PreventRunKeyDelete" BinaryKey="CustomActionsDll" DllEntry="PreventRunKeyDelete" Execute="immediate" /> <InstallExecuteSequence> <Custom Action="PreventRunKeyDelete" Before="RemoveRegistryValues">REMOVE="ALL"</Custom> </InstallExecuteSequence>
为什么之前的方法无效?
Wix的RegistryKey/@action='createKey'仅保证安装时Run项被创建,但卸载时如果项内无任何值,MSI的默认清理逻辑还是会删除它——这个属性无法阻止卸载阶段的项删除。
内容的提问来源于stack exchange,提问作者TroyT
相关产品推荐
相关产品推荐

