WiX: faire un lien symbolique avec l'UAC activé
-
26-09-2019 - |
Question
Je veux exécuter une action personnalisée dans un environnement Windows Installer (avec le script WiX) qui établit des liens symboliques à la fin de l'installation. mklink nécessite des privilèges d'administrateur, comme le programme d'installation restreint. C'est ce que je l'ai écrit:
<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>
Cela fonctionne parfaitement si l'UAC est complètement désactivé. Cependant, lors de l'activation de contrôle de compte tous les niveaux, cette action personnalisée échoue avec
CAQuietExec: You do not have sufficient privilege to perform this operation.
même si je laissais dans la fenêtre de consentement. J'ai essayé de changer Exécuter à différé, Impersonate à pas, ou les InstallPrivileges de paquet de changement à élevée, aucun d'entre eux fonctionne.
Toute suggestion que je peux contourner? Merci!
Modifier : Code révisé avec l'action différée personnalisée
<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>
La solution
fonctionne-t-il lorsqu'il est lancé à partir d'une commande administrateur rapide? Je suppose qu'il fait.
D'après ce que j'ai trouvé le msi ne peut pas augmenter le niveau qui est ce que l'UAC vous avez besoin. Je devais créer un setup.exe qui enveloppa le msi comme une ressource intégrée et l'a exécuté. Le setup.exe comprend le niveau d'exécution de la demande d'administrateur app.manifest qui soulève de manière appropriée le niveau 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>
je comprends tout simplement pas WIX, des actions personnalisées et assez contrôle de compte, mais c'est ce que je fini par faire.
Autres conseils
Êtes-vous le programmer entre InstallInitialize et InstallFinalize lorsque vous marquez Différé? Votre Avant et après l'air un peu bizarre:
InstallFinalize
_cmdline avant InstallFinalize
_mkline_exec après _cmdline
Sons un peu nondéterministe. Vous trouverez peut-être _cmdline survenant après InstallFinalize et différé, il ne fonctionnera pas.
Essayez:
InstallFinalize
_exec avant InstallFinalize
_cmldline avant _exec
Si elle est en fait MKLINK qui exige l'élévation, vous pouvez essayer d'utiliser Sysinternals junction.exe à la place.
J'ai fini par elevate.exe de Wintellect regrouper, déployer quelque dossier temporaire et lui fournir un chemin de script de ligne qui a créé tous les liens symboliques. Qu'il a été invoqué par l'action personnalisée. fichier de ligne de commande à son tour, a une certaine bonté à l'intérieur pour détecter le dossier approprié des fichiers de programme. ou l'obtenir à partir de la ligne de commande, si nécessaire. Il semble que même si WiX correctement élève l'action personnalisée, msi (ou Windows Installer) lui-même ne lui accorde pas de droits suffisants pour exécuter correctement mklink commande.
Notez également que Impersonate = "yes" dans le CA. Je crois que ce qui laissera msi pour montrer la boîte de dialogue d'élévation quand il exécute l'action.
fichier ligne de commande:
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"
dans le fichier 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>