views:

96

answers:

2

Hello. 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>
A: 

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

Christopher Painter
I tried your suggestion, and get the same error. The following are what I changed: 1) cmdline actions' properties become the Id of the exec actions; 2) Add Execute="deferred" and Impersonate="no" to all exec actions; 3) fix the execute sequence. I confirmed the sequence with Orca. Everything is before InstallFinalize.
Crend King
A: 

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 appropriatly:

<?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"&gt;
    <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>

I may just not understand WIX, custom actions and UAC enough, but this is what I ended up doing.

Mitch