WiX:在启用 UAC 的情况下建立符号链接
我想在 Windows Installer(使用 WiX 脚本)中执行自定义操作,在安装结束时创建符号链接。 mklink 需要管理员权限,因为安装程序有限制。这就是我写的:
<CustomAction Id="mklink_cmdline" Property="QtExecCmdLine" Value='"[SystemFolder]cmd.exe" /c mklink "[SystemFolder]my_app.dll" "[INSTALLDIR]my_app.dll"' />
<CustomAction Id="mklink_exec" BinaryKey="WixCA" DllEntry="CAQuietExec" Return="ignore" />
...
<InstallExecuteSequence>
<Custom Action="mklink_cmdline" Before="InstallFinalize">
...
</Custom>
<Custom Action="mklink_exec" After="mklink_cmdline">
...
</Custom>
...
</InstallExecuteSequence>
如果 UAC 完全禁用,这将非常有效。但是,在任何级别启用 UAC 时,
CAQuietExec: You do not have sufficient privilege to perform this operation.
即使我在同意窗口中允许,此自定义操作也会失败。我尝试将“执行”更改为“延迟”,将“模拟”更改为“否”,或将包的“InstallPrivileges”更改为“提升”,但这些都不起作用。
有什么建议我可以绕过吗?谢谢你!
编辑:使用延迟的自定义操作修改代码
<CustomAction Id="mklink_cmdline" Property="mklink_exec" Value='"[SystemFolder]cmd.exe" /c mklink "[SystemFolder]my_app.dll" "[INSTALLDIR]my_app.dll"' />
<CustomAction Id="mklink_exec" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Impersonate="no" Return="ignore" />
...
<InstallExecuteSequence>
<Custom Action="mklink_exec" Before="InstallFinalize">
...
</Custom>
<Custom Action="mklink_cmdline" Before="mklink_exec">
...
</Custom>
...
</InstallExecuteSequence>
I want to execute a custom action in a Windows Installer (with WiX script) that makes symbolic links at the end of installation. mklink requires administrator privilege, as the installer restricts. This is what I wrote:
<CustomAction Id="mklink_cmdline" Property="QtExecCmdLine" Value='"[SystemFolder]cmd.exe" /c mklink "[SystemFolder]my_app.dll" "[INSTALLDIR]my_app.dll"' />
<CustomAction Id="mklink_exec" BinaryKey="WixCA" DllEntry="CAQuietExec" Return="ignore" />
...
<InstallExecuteSequence>
<Custom Action="mklink_cmdline" Before="InstallFinalize">
...
</Custom>
<Custom Action="mklink_exec" After="mklink_cmdline">
...
</Custom>
...
</InstallExecuteSequence>
This works perfectly if UAC is completely disabled. However, when enabling UAC in any level, this custom action fails with
CAQuietExec: You do not have sufficient privilege to perform this operation.
even if I allowed in the consent window. I tried to change Execute to deferred, Impersonate to no, or change package's InstallPrivileges to elevated, none of them works.
Any suggestion I can bypass? Thank you!
Edit: revised code with deferred custom action
<CustomAction Id="mklink_cmdline" Property="mklink_exec" Value='"[SystemFolder]cmd.exe" /c mklink "[SystemFolder]my_app.dll" "[INSTALLDIR]my_app.dll"' />
<CustomAction Id="mklink_exec" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Impersonate="no" Return="ignore" />
...
<InstallExecuteSequence>
<Custom Action="mklink_exec" Before="InstallFinalize">
...
</Custom>
<Custom Action="mklink_cmdline" Before="mklink_exec">
...
</Custom>
...
</InstallExecuteSequence>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
从管理员命令提示符运行时它是否有效?我想确实如此。
据我发现,msi 无法提高 UAC 级别,而这正是您所需要的。我必须创建一个 setup.exe,将 msi 包装为嵌入式资源并执行它。 setup.exe 包含请求管理员执行级别的 app.manifest,该级别会适当提高 UAC 级别:
我可能对 WIX、自定义操作和 UAC 不够了解,但这就是我最终所做的。
Does it work when ran from an administrator command prompt? I assume it does.
From what I found the msi cannot raise the UAC level which is what you need here. I had to create a setup.exe that wrapped the msi as an embedded resource and executed it. The setup.exe includes the app.manifest requesting administrator execution level which raises the UAC level appropriately:
I may just not understand WIX, custom actions and UAC enough, but this is what I ended up doing.
当您将其标记为“延迟”时,是否将其安排在 InstallInitialize 和 InstallFinalize 之间?您的之前和之后看起来有点奇怪:
InstallFinalize
_cmdline before InstallFinalize
_mkline_exec after _cmdline
听起来有点不确定。您可能会发现 _cmdline 在 InstallFinalize 之后发生,并且 deferred 在那里不起作用。
尝试:
InstallFinalize
_exec 之前 InstallFinalize
_cmldline 之前 _exec
Are you scheduling it between InstallInitialize and InstallFinalize when you mark it for Deferred? Your Before and after looks a little wierd:
InstallFinalize
_cmdline before InstallFinalize
_mkline_exec after _cmdline
Sounds a little nondeterministic. You might find _cmdline occurring after InstallFinalize and deferred won't work there.
Try:
InstallFinalize
_exec before InstallFinalize
_cmldline before _exec
如果实际上是 mklink 需要提升,您可以尝试使用 SysInternals junction.exe。
If it's actually mklink that is requiring elevation, you might try using SysInternals junction.exe instead.
我最终将 wintellect 中的 elevate.exe 捆绑在一起,将其部署到某个临时文件夹,并为其提供创建所有符号链接的命令行脚本的路径。比它是通过自定义操作调用的。
命令行文件又具有一些优点来检测正确的程序文件文件夹。或者如果需要的话从命令行获取它。
看来,即使 WiX 正确地提升了自定义操作,msi(或 Windows Installer)本身也没有授予它足够的权限来正确运行 mklink 命令。
另请注意 CA 中的Impersonate="yes"。我相信这将使 msi 在执行操作时显示海拔对话框。
命令行文件:
在wxs文件中:
I ended up bundling elevate.exe from wintellect, deploy it to some temp folder and supply it with a path to command-line script which created all symbolic links. Than it was invoked via the custom action.
Command line file in turn has some goodness inside to detect proper program files folder. or get it from the command line, if needed.
It appears that even though WiX correctly elevates the custom action, msi (or Windows Installer) itself doesn't grant it sufficient rights to properly run mklink command.
Also note that Impersonate="yes" in the CA. I believe that's what will let msi to show elevation dialog box when it executes the action.
command line file:
in the wxs file: