WiX:启用UAC的符号链接

时间:2010-08-31 17:17:45

标签: wix uac custom-action

我想在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>

4 个答案:

答案 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="&quot;[TempFolder]\elevate.exe&quot; &quot;[TempFolder]\makesymlinks.cmd&quot;" />
<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>