我想在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.
即使我允许进入同意窗口。我尝试将Execute更改为deferred,将Impersonate更改为no,或将package的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>
答案 0 :(得分:1)
从管理员命令提示符运行时是否有效?我认为确实如此。
从我发现的msi无法提高你所需要的UAC级别。我不得不创建一个setup.exe,它将msi包装为嵌入式资源并执行它。 setup.exe包括请求管理员执行级别的app.manifest,它适当地提高了UAC级别:
<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<assemblyIdentity version="1.0.0.0" name="Setup.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
</asmv1:assembly>
我可能只是不了解WIX,自定义操作和UAC,但这就是我最终要做的。
答案 1 :(得分:0)
当您将其标记为Deferred时,是否在InstallInitialize和InstallFinalize之间安排它?你之前和之后看起来有点奇怪:
InstallFinalize
在InstallFinalize之前_cmdline
_cmdline 后的_mkline_exec
听起来有点不确定。您可能会发现在InstallFinalize之后发生了_cmdline,而deferred将无法在那里工作。
尝试:
InstallFinalize
在InstallFinalize之前_exec
_cmldline _exec
之前答案 2 :(得分:0)
如果它实际上是需要提升的mklink,您可以尝试使用SysInternals junction.exe。
答案 3 :(得分:0)
我最终从wintellect捆绑了elevate.exe,将其部署到某个临时文件夹,并为其提供了一个命令行脚本的路径,该脚本创建了所有符号链接。比通过自定义操作调用它。 命令行文件反过来有一些好处,以检测正确的程序文件文件夹。或者,如果需要,从命令行获取它。 看来即使WiX正确提升自定义操作,msi(或Windows Installer)本身也不会授予它足够的权限来正确运行mklink命令。
另请注意CA中的 Impersonate =“yes”。我相信这会让msi在执行操作时显示高程对话框。
命令行文件:
cd /D %~p0
IF EXIST "%PROGRAMFILES(x86)%" SET PROGFILES=%PROGRAMFILES(x86)%
IF "%PROGFILES%".=="". SET PROGFILES=%PROGRAMFILES%
SET INSTALLPATH=%PROGFILES%\MyGreatProduct
SET DATAPATH=%PROGRAMDATA%\MyGreatProduct
IF NOT "%~1."=="." SET INSTALLPATH=%~1
IF NOT "%~2."=="." SET DATAPATH=%~2
IF EXIST "%INSTALLPATH%" mklink "%INSTALLPATH%\veryimportant.ini" "%DATAPATH%\veryimportant.ini"
wxs文件中的:
<Component Directory="TempFolder" Id='Comp_Temp_Makesymlinks' Guid='47a58219-1291-4321-4321-176987154921'>
<File Id='makesymlinks_cmd' Source='makesymlinks.cmd'>
<Permission User='Everyone' GenericAll='yes' />
</File>
<File Id='elevate_exe' Source='elevate.exe'>
<Permission User='Everyone' GenericAll='yes' />
</File>
</Component>
<SetProperty Id="CA_MakeSymLinksCmd" Before="CA_MakeSymLinksCmd" Sequence="execute"
Value=""[TempFolder]\elevate.exe" "[TempFolder]\makesymlinks.cmd"" />
<CustomAction Id="CA_MakeSymLinksCmd" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="ignore" Impersonate="yes" />
<InstallExecuteSequence>
<Custom Action="CA_MakeSymLinksCmd" Before="InstallFinalize"><![CDATA[NOT Installed AND VersionNT >= 600 ]]></Custom>
</InstallExecuteSequence>