我有一个用WiX构建的MSI。它执行以下自定义操作:
<CustomAction Id='StartTray'
Directory='INSTALLDIR'
ExeCommand='[INSTALLDIR]myapptray.exe'
Return='asyncNoWait'
Impersonate='no'
Execute='deferred' />
它的安排是这样的:
<Custom Action='StartTray' After='StartServices'>NOT Installed OR (TRAYWASRUNNING AND NOT REMOVE~="ALL")</Custom>
myapptray.exe
碰巧使用模拟从其本地系统的起始上下文(从 MSI 上下文运行)重新启动自身,作为当前在桌面上处于活动状态的用户。这不在我的控制范围内,Imanalogate='yes' 不起作用,因为可能会从系统服务的上下文调用 MSI 进行升级,这意味着 Imanalogate='yes' 最终仍将作为本地系统运行应用程序。
我最近从将VC9 CRT作为MSM包含在此MSI中,转变为将其包含在引导程序exe中。
这样做会阻止myapptray.exe
自定义操作成功运行。模拟在 WTSQueryUserToken
中失败,返回ERROR_PRIVILEGE_NOT_HELD
。这似乎意味着删除 MSM 实际上改变了运行 MSI 的用户上下文,但这似乎很荒谬。我从wxs文件中删除的唯一行是MSM的<Merge>
和<MergeRef>
标签,其他任何内容都没有改变。
我做错了什么?
我会更多地查看您的 EXE 是针对哪些版本的 CRT 构建的,以及是否有任何策略规则说明它可以针对什么运行。 在 MSI 之前从 MSM 迁移到 EXE 运行通常是一件好事。
顺便说一句,我曾经做过这样的事情。 我们必须使用 MSI 在系统上下文中推出 MSI。 如果用户已登录,则必须使用用户桌面登录会话重新启动应用程序。 我安装了一个 DCOM 服务器,配置为模拟交互式用户来完成此操作。 真的很奇怪,但有一个正当的理由。
不过,这一切都是在重新启动管理器之前。
我想通了。
CRT MSM 将 ALLUSERS=1 设置为 ALLUSERS=1,安装程序的行为发生了变化,因为它不存在于我们的基本安装程序中。因此,MSM 的 ALLUSERS 设置继承到基本安装程序中。
在我们的 wxs 文件中设置 ALLUSERS=1 解决了这个问题!