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>
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:
<?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>
I may just not understand WIX, custom actions and UAC enough, but this is what I ended up doing.