能否让Wix延迟Custom Action同时模拟用户并以提升权限运行?
问题描述
我有一个需要修改注册表的Custom Action,它有以下要求:
- 为支持回滚,标记为
deferred - 修改注册表需要以**提升权限(elevated priviliges)**运行
- 必须在**特定用户的安全上下文(模拟)**下运行
当前的配置代码如下:
<CustomAction Id="EncryptRegistrySettings" BinaryKey="DLServiceCA" DllEntry="EncryptRegistrySettings" Execute="deferred" Impersonate="yes" Return="check"/>
我有一些不太理想的替代方案(比如设置Execute="immediate",或在impersonate="yes"时使用提升权限的子进程),但不想采用这些方案。
当前遇到的问题:
- 当设置
Impersonate="no"时,msiexec子进程以SYSTEM身份运行,无法模拟特定用户 - 当设置
Impersonate="yes"时,以当前用户身份运行,但没有提升权限,无法完成注册表修改
我的核心问题是:能否让Deferred类型的Custom Action同时以模拟用户(Impersonated)和提升权限(elevated)的方式运行?
解答
不行,Windows Installer的Deferred Custom Action无法同时满足「模拟特定用户」和「提升权限」这两个要求,这是由Windows Installer的执行模型决定的:
Deferred Action的权限规则
- 当
Impersonate="yes"时,Deferred Action会在发起安装的用户上下文下运行,但这个上下文没有提升权限——即使安装本身是通过UAC提升启动的,模拟用户的Deferred Action也会丢失提升权限,因为Windows Installer会在非提升的用户令牌下执行它。 - 当
Impersonate="no"时,Deferred Action会以SYSTEM身份运行,拥有完全的提升权限,但无法模拟特定用户的安全上下文。
- 当
为什么替代方案是不可避免的
你提到的两个替代方案其实是Windows Installer模型下仅有的可行路径:- 设置
Execute="immediate":Immediate Action可以在提升的用户上下文下运行(如果安装是提升启动的),但它不支持回滚,而且Immediate阶段不推荐修改系统状态(比如注册表),因为这会破坏MSI的事务性。 - 在
Impersonate="yes"的Deferred Action中启动提升权限的子进程:这是相对更合规的方式——你可以在自定义动作中使用CreateProcessWithLogonW或类似API,以提升权限的方式启动子进程来修改注册表。虽然这会额外引入子进程,但它能同时满足模拟用户和提升权限的要求,且保留Deferred Action的回滚支持。
- 设置
额外的折中思路
如果你的注册表修改是针对用户特定的位置(比如HKCU),可以考虑将修改拆分:- 用
Impersonate="yes"的Deferred Action修改用户注册表(不需要提升权限) - 用
Impersonate="no"的Deferred Action修改系统级注册表(需要提升权限)
但这只适用于注册表操作可以拆分的场景。
- 用
内容的提问来源于stack exchange,提问作者Sergey Kolesnik
相关产品推荐
相关产品推荐

