Il existe un moyen simple sans avoir besoin d'utiliser un outil externe - il fonctionne bien avec Windows 7, 8, 8.1 et 10 et est également rétrocompatible (Windows XP n'a pas d'UAC, donc l'élévation n'est pas nécessaire - en ce sens cas où le script se poursuit).
Consultez ce code (je me suis inspiré du code de NIronwolf publié dans le fil Batch File - "Access Denied" Sur Windows 7? ), Mais je l'ai amélioré - dans ma version, il n'y a pas de répertoire créé et supprimé pour vérifier les privilèges d'administrateur):
::::::::::::::::::::::::::::::::::::::::::::
:: Elevate.cmd - Version 4
:: Automatically check & get admin rights
:: see "https://stackoverflow.com/a/12264592/1016343" for description
::::::::::::::::::::::::::::::::::::::::::::
@echo off
CLS
ECHO.
ECHO =============================
ECHO Running Admin shell
ECHO =============================
:init
setlocal DisableDelayedExpansion
set cmdInvoke=1
set winSysFolder=System32
set "batchPath=%~0"
for %%k in (%0) do set batchName=%%~nk
set "vbsGetPrivileges=%temp%\OEgetPriv_%batchName%.vbs"
setlocal EnableDelayedExpansion
:checkPrivileges
NET FILE 1>NUL 2>NUL
if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges )
:getPrivileges
if '%1'=='ELEV' (echo ELEV & shift /1 & goto gotPrivileges)
ECHO.
ECHO **************************************
ECHO Invoking UAC for Privilege Escalation
ECHO **************************************
ECHO Set UAC = CreateObject^("Shell.Application"^) > "%vbsGetPrivileges%"
ECHO args = "ELEV " >> "%vbsGetPrivileges%"
ECHO For Each strArg in WScript.Arguments >> "%vbsGetPrivileges%"
ECHO args = args ^& strArg ^& " " >> "%vbsGetPrivileges%"
ECHO Next >> "%vbsGetPrivileges%"
if '%cmdInvoke%'=='1' goto InvokeCmd
ECHO UAC.ShellExecute "!batchPath!", args, "", "runas", 1 >> "%vbsGetPrivileges%"
goto ExecElevation
:InvokeCmd
ECHO args = "/c """ + "!batchPath!" + """ " + args >> "%vbsGetPrivileges%"
ECHO UAC.ShellExecute "%SystemRoot%\%winSysFolder%\cmd.exe", args, "", "runas", 1 >> "%vbsGetPrivileges%"
:ExecElevation
"%SystemRoot%\%winSysFolder%\WScript.exe" "%vbsGetPrivileges%" %*
exit /B
:gotPrivileges
setlocal & cd /d %~dp0
if '%1'=='ELEV' (del "%vbsGetPrivileges%" 1>nul 2>nul & shift /1)
::::::::::::::::::::::::::::
::START
::::::::::::::::::::::::::::
REM Run shell as admin (example) - put here code as you like
ECHO %batchName% Arguments: P1=%1 P2=%2 P3=%3 P4=%4 P5=%5 P6=%6 P7=%7 P8=%8 P9=%9
cmd /k
Le script tire parti du fait qu'il NET FILE
nécessite des privilèges d'administrateur et revient errorlevel 1
si vous ne l'avez pas. L'élévation est obtenue en créant un script qui relance le fichier de commandes pour obtenir des privilèges. Cela amène Windows à présenter la boîte de dialogue UAC et vous demande le compte administrateur et le mot de passe.
Je l'ai testé avec Windows 7, 8, 8.1, 10 et Windows XP - cela fonctionne bien pour tous. L'avantage est qu'après le point de départ, vous pouvez placer tout ce qui nécessite des privilèges d'administrateur système, par exemple, si vous avez l'intention de réinstaller et de réexécuter un service Windows à des fins de débogage (en supposant que mypackage.msi est un package d'installation de service) :
msiexec /passive /x mypackage.msi
msiexec /passive /i mypackage.msi
net start myservice
Sans ce script d'élévation de privilèges, l'UAC vous demanderait à trois reprises votre nom d'utilisateur et votre mot de passe administrateur - maintenant, vous n'êtes demandé qu'une seule fois au début, et uniquement si nécessaire.
Si votre script a juste besoin d'afficher un message d'erreur et de quitter s'il n'y a pas de privilèges d'administrateur au lieu d'une élévation automatique, c'est encore plus simple: vous pouvez y parvenir en ajoutant ce qui suit au début de votre script:
@ECHO OFF & CLS & ECHO.
NET FILE 1>NUL 2>NUL & IF ERRORLEVEL 1 (ECHO You must right-click and select &
ECHO "RUN AS ADMINISTRATOR" to run this batch. Exiting... & ECHO. &
PAUSE & EXIT /D)
REM ... proceed here with admin rights ...
De cette façon, l'utilisateur doit cliquer avec le bouton droit et sélectionner "Exécuter en tant qu'administrateur" . Le script se poursuivra après l' REM
instruction s'il détecte des droits d'administrateur, sinon quittez avec une erreur. Si vous n'en avez pas besoin PAUSE
, supprimez-le.
Important: NET FILE [...] EXIT /D)
doit être sur la même ligne. Il est affiché ici sur plusieurs lignes pour une meilleure lisibilité!
Sur certaines machines, j'ai rencontré des problèmes, qui sont déjà résolus dans la nouvelle version ci-dessus. L'un était dû à une gestion différente des guillemets doubles, et l'autre problème était dû au fait que l'UAC était désactivé (défini au niveau le plus bas) sur une machine Windows 7, d'où le script s'appelle encore et encore.
J'ai corrigé cela maintenant en supprimant les guillemets dans le chemin d'accès et en les rajoutant plus tard, et j'ai ajouté un paramètre supplémentaire qui est ajouté lorsque le script se relance avec des droits élevés.
Les guillemets doubles sont supprimés par les éléments suivants (les détails sont ici ):
setlocal DisableDelayedExpansion
set "batchPath=%~0"
setlocal EnableDelayedExpansion
Vous pouvez ensuite accéder au chemin à l'aide de !batchPath!
. Il ne contient pas de guillemets doubles, il est donc sûr de le dire "!batchPath!"
plus tard dans le script.
La ligne
if '%1'=='ELEV' (shift & goto gotPrivileges)
vérifie si le script a déjà été appelé par le script VBScript pour élever les droits, évitant ainsi des récursions sans fin. Il supprime le paramètre à l'aide de shift
.
Mettre à jour:
Pour éviter d'avoir à enregistrer l' .vbs
extension dans Windows 10 , j'ai remplacé la ligne
"%temp%\OEgetPrivileges.vbs"
par
"%SystemRoot%\System32\WScript.exe" "%temp%\OEgetPrivileges.vbs"
dans le script ci-dessus; également ajouté cd /d %~dp0
comme suggéré par Stephen (réponse séparée) et par Tomáš Zato (commentaire) pour définir le répertoire de script par défaut.
Maintenant, le script honore les paramètres de ligne de commande qui lui sont transmis. Merci à jxmallet, TanisDLJ et Peter Mortensen pour leurs observations et inspirations.
Selon l'indice d'Artjom B., je l'ai analysé et l'ai remplacé SHIFT
par SHIFT /1
, qui préserve le nom de fichier du %0
paramètre
Ajouté del "%temp%\OEgetPrivileges_%batchName%.vbs"
à la :gotPrivileges
section à nettoyer (comme suggéré par mlt ). Ajouté %batchName%
pour éviter l'impact si vous exécutez différents lots en parallèle. Notez que vous devez utiliser for
pour pouvoir profiter des fonctions de chaîne avancées, telles que %%~nk
, qui extrait uniquement le nom de fichier.
Structure de script optimisée, améliorations (variable ajoutée vbsGetPrivileges
qui est désormais référencée partout permettant de changer facilement le chemin ou le nom du fichier, ne supprimez le .vbs
fichier que si le lot devait être élevé)
Dans certains cas, une syntaxe d'appel différente était requise pour l'élévation. Si le script ne fonctionne pas, vérifiez les paramètres suivants:
set cmdInvoke=0
set winSysFolder=System32
Modifiez le 1er paramètre en set cmdInvoke=1
et vérifiez si cela résout déjà le problème. Il s'ajoutera cmd.exe
au script effectuant l'élévation.
Ou essayez de changer le 2e paramètre en winSysFolder=Sysnative
, cela pourrait aider (mais n'est pas nécessaire dans la plupart des cas) sur les systèmes 64 bits. (ADBailey l'a rapporté). "Sysnative" n'est requis que pour lancer des applications 64 bits à partir d'un hôte de script 32 bits (par exemple, un processus de génération Visual Studio ou un appel de script à partir d'une autre application 32 bits).
Pour rendre plus clair comment les paramètres sont interprétés, je les affiche maintenant comme P1=value1 P2=value2 ... P9=value9
. Ceci est particulièrement utile si vous devez mettre des paramètres comme des chemins entre guillemets doubles, par exemple "C:\Program Files"
.
Si vous souhaitez déboguer le script VBS, vous pouvez ajouter le //X
paramètre à WScript.exe comme premier paramètre, comme suggéré ici (il est décrit pour CScript.exe, mais fonctionne également pour WScript.exe).
Liens utiles: