269 votes

Comment puis-je élever automatiquement mon fichier batch, de sorte qu'il demande des droits d'administrateur UAC si nécessaire ?

Je veux que mon fichier batch ne s'exécute qu'en mode élevé. S'il n'est pas exécuté en mode élévation, il faut prévoir une option permettant à l'utilisateur de relancer le lot en mode élévation.

Je suis en train d'écrire un fichier batch pour définir une variable système, copier deux fichiers dans un fichier Fichiers de programme et lancer l'installation du pilote. Si un utilisateur de Windows 7/Windows Vista ( UAC et même s'il s'agit d'un administrateur local) l'exécute sans cliquer avec le bouton droit de la souris et sélectionner "Exécuter en tant qu'administrateur", il obtiendra "Accès refusé" en copiant les deux fichiers et en écrivant la variable système.

Je voudrais utiliser une commande pour redémarrer automatiquement le lot en tant qu'élevé si l'utilisateur est en fait un administrateur. Sinon, s'il n'est pas administrateur, je veux lui dire qu'il a besoin des privilèges d'administrateur pour exécuter le fichier batch. J'utilise xcopy pour copier les fichiers et REG ADD pour écrire la variable système. J'utilise ces commandes pour traiter d'éventuelles machines Windows XP. J'ai trouvé des questions similaires sur ce sujet, mais rien qui ne traite de la relance d'un fichier batch en mode élevé.

2 votes

Regardez ce que j'ai posté - vous n'avez pas besoin d'un outil externe, le script vérifie automatiquement les droits d'administrateur et s'élève automatiquement si nécessaire.

1 votes

Veuillez considérer si la réponse de Matt serait la réponse cochée ? S

1 votes

371voto

Matt Points 3445

Il est un moyen facile, sans avoir à utiliser un outil externe - il fonctionne très bien avec Windows 7 et est rétro-compatible (Windows XP n'a pas de contrôle de compte d'utilisateur, donc pas d'élévation est nécessaire - dans ce cas, le script continue simplement).

Découvrez ce code (j'ai été inspiré par le code ici, mais je me suis amélioré dans ma version il n'y a pas de répertoire créé et supprimé pour vérifier les privilèges d'administrateur):

:::::::::::::::::::::::::::::::::::::::::
:: Automatically check & get admin rights
:::::::::::::::::::::::::::::::::::::::::
@echo off
CLS 
ECHO.
ECHO =============================
ECHO Running Admin shell
ECHO =============================

:checkPrivileges 
NET FILE 1>NUL 2>NUL
if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges ) 

:getPrivileges 
if '%1'=='ELEV' (shift & goto gotPrivileges)  
ECHO. 
ECHO **************************************
ECHO Invoking UAC for Privilege Escalation 
ECHO **************************************

setlocal DisableDelayedExpansion
set "batchPath=%~0"
setlocal EnableDelayedExpansion
ECHO Set UAC = CreateObject^("Shell.Application"^) > "%temp%\OEgetPrivileges.vbs" 
ECHO UAC.ShellExecute "!batchPath!", "ELEV", "", "runas", 1 >> "%temp%\OEgetPrivileges.vbs" 
"%temp%\OEgetPrivileges.vbs" 
exit /B 

:gotPrivileges 
::::::::::::::::::::::::::::
::START
::::::::::::::::::::::::::::
setlocal & pushd .

REM Run shell as admin (example) - put here code as you like
cmd /k

Le script prend avantage du fait qu' NET FILE nécessite le privilège admin et les retours errorlevel 1 si vous ne l'avez pas. L'élévation est réalisé en créant un script qui re-lance le fichier de commandes pour obtenir des privilèges. Cela permet à Windows de présenter la boîte de dialogue contrôle de compte d'utilisateur et vous demande pour le compte admin et le mot de passe.

Je l'ai testé avec Windows 7 et Windows XP fonctionne bien pour les deux. L'avantage est, après le point de départ, vous pouvez placer tout ce qui requiert des privilèges d'administrateur, par exemple, si vous avez l'intention de ré-installer et ré-exécuter un service Windows fin de débogage (suppose que mypackage.msi est un service package d'installation):

msiexec /passive /x mypackage.msi
msiexec /passive /i mypackage.msi
net start myservice

Sans ce privilège élévation de script de contrôle de compte d'utilisateur vous demande trois fois pour votre compte d'utilisateur admin et le mot de passe - maintenant vous êtes demandé qu'une seule fois au début, et seulement si nécessaire.


Mise à jour: Si votre script ne doit afficher un message d'erreur et la sortie si il n'y a pas de privilèges d'administrateur à la place de l'auto-élévatrices, c'est encore plus simple: Vous pouvez atteindre cet objectif 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électionnez "Exécuter en tant qu'administrateur". Le script va procéder, après l' REM déclaration si elle détecte les droits d'admin, sinon la sortie avec une erreur. Si vous n'avez pas besoin de l' PAUSE, suffit de le retirer. Important: NET FILE [...] EXIT /D) doit être dans la même ligne, il est affiché ici en plusieurs lignes pour une meilleure lisibilité!


Mise à jour: Sur certaines machines, j'ai rencontré des problèmes qui sont résolus dans la nouvelle version ci-dessus déjà. L'un était dû à différents devis double manipulation, l'autre problème était dû au fait que l'UAC est désactivé (niveau le plus bas) sur une machine Windows 7, d'où le script s'appelle elle-même, encore et encore.

J'ai fixé cette maintenant en enlevant les guillemets dans le chemin d'accès et le rajouter plus tard et j'ai ajouté un paramètre supplémentaire qui est ajouté lorsque le script re-lance avec des droits élevés.

Supprimer les guillemets doubles par le texte suivant (les détails sont ici):

setlocal DisableDelayedExpansion
set "batchPath=%~0"
setlocal EnableDelayedExpansion

Vous pouvez ensuite accéder au chemin d'accès en utilisant !batchPath!, il ne contient pas de guillemets, de sorte qu'il est sûr de 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 VBS pour but d'élever les droits, donc en évitant les interminables récurrences. Il supprime le paramètre à l'aide de shift.

19 votes

Excellente réponse, même si cela m'étonne un peu que vous deviez faire tout cela pour faire quelque chose qui est clairement nécessaire dans certains cas.

68 votes

En effet, une commande telle que ELEVATE est clairement absente du langage batch de Windows.

2 votes

Peut-être que c'est plus facile avec powershell qui semble être le langage de script approuvé pour les choses plus complexes, mais je n'ai jamais pris la peine de l'apprendre jusqu'à présent :(

65voto

Ir Relevant Points 161

Comme jcoder et Matt l'ont mentionné, PowerShell l'a rendu facile, et il pouvait même être intégré dans le lot script sans créer un nouveau script.

J'ai modifié le script de Matt :

:: Check privileges 
net file 1>NUL 2>NUL
if not '%errorlevel%' == '0' (
    powershell Start-Process -FilePath "%0" -ArgumentList "%cd%" -verb runas >NUL 2>&1
    exit /b
)

:: Change directory with passed argument. Processes started with
:: "runas" start with forced C:\Windows\System32 workdir
cd /d %1

:: Actual work

3 votes

Vous avez raison, si PowerShell est installé, vous pouvez l'utiliser pour exécuter le fichier batch avec élévation (merci pour l'extrait de code !). Et oui, l'étiquette n'est pas nécessaire. Merci pour les conseils, cela vaut un +1 ... :-)

2 votes

Lorsqu'il est invoqué depuis cmd, Powershell.exe n'a pas l'option -verb runas. Elle existe si vous êtes déjà dans PowerShell.

1 votes

J'aime vraiment cette solution, elle fonctionne très bien pour moi. Sous Windows 8.1, j'ai eu besoin de l'étiquette :gotPrivileges pour que cela fonctionne.

31voto

Stephen Points 346

J'utilise l'excellente réponse de Matt, mais je constate une différence entre mes systèmes Windows 7 et Windows 8 lors de l'exécution de scripts élevés.

Une fois que le script est élevé sous Windows 8, le répertoire courant est fixé à C:\Windows\system32 . Heureusement, il existe une solution de contournement facile en changeant le répertoire courant par le chemin du script courant :

cd /d %~dp0

Note : Utilisez cd /d pour s'assurer que la lettre du lecteur est également modifiée.

Pour tester cela, vous pouvez copier ce qui suit dans un script. Exécutez normalement sur l'une ou l'autre version pour voir le même résultat. Exécutez en tant qu'administrateur et voyez la différence sous Windows 8 :

@echo off
echo Current path is %cd%
echo Changing directory to the path of the current script
cd %~dp0
echo Current path is %cd%
pause

1 votes

Bonne astuce, Stephen. Donc le script devrait se terminer par cd %~dp0 pour conserver son chemin actuel (je suppose que cela fonctionne aussi dans Win7, donc la même commande peut être utilisée bien que seulement nécessaire pour Win8+). +1 pour cela !

2 votes

A noter que cela était également nécessaire sur mon système fonctionnant sous Windows 7.

1 votes

Ou utiliser pushd %~dp0 au lieu de... pourquoi ? parce que popd

25voto

ewall Points 10676

Vous pouvez faire en sorte que le script s'appelle lui-même avec psexec 's -h pour l'exécution en mode élevé.

Je ne sais pas comment détecter s'il est déjà exécuté en mode élevé ou non... peut-être réessayer avec des perms élevés seulement s'il y a une erreur d'accès refusé ?

Ou bien, vous pourriez simplement avoir les commandes de l'option xcopy y reg.exe toujours être exécuté avec psexec -h mais il serait ennuyeux pour l'utilisateur final de devoir saisir son mot de passe à chaque fois (ou peu sûr si vous incluiez le mot de passe dans le script)...

12 votes

Merci pour la réponse. Malheureusement, je ne pense pas pouvoir utiliser d'autres outils que ceux de Windows Vista/7, car ce logiciel sera destiné à des clients extérieurs à mon bureau. Je ne pense pas pouvoir distribuer PSExec légalement.

2 votes

Oui, je pense que tu as raison - même si PSExec est maintenant un outil Microsoft (depuis qu'ils ont racheté les gars de Sysinternals !), le CLUF interdit la distribution :(

2 votes

Je pense que mes options sont assez limitées. Si je savais coder en VB, je pourrais en faire un exe avec un manifeste administrateur, mais je ne saurais même pas par où commencer. Je pense que je vais simplement avertir au début du lot qu'il faut l'exécuter en tant qu'administrateur s'ils utilisent Windows Vista/7. Merci à tous.

24voto

Ryan Bemrose Points 1025

J'utilise PowerShell pour relancer le script élevé s'il ne l'est pas. Mettez ces lignes tout en haut de votre script.

net file 1>nul 2>nul && goto :run || powershell -ex unrestricted -Command "Start-Process -Verb RunAs -FilePath '%comspec%' -ArgumentList '/c %~fnx0 %*'"
goto :eof
:run
:: TODO: Put code here that needs elevation

J'ai copié la méthode "net name" de la réponse de @Matt. Sa réponse est bien mieux documentée et comporte des messages d'erreur, etc. Celle-ci a l'avantage que PowerShell est déjà installé et disponible sur Windows 7 et plus. Pas de fichiers VBScript (*.vbs) temporaires, et vous n'avez pas à télécharger d'outils.

Cette méthode devrait fonctionner sans aucune configuration ou paramétrage, tant que vos autorisations d'exécution PowerShell ne sont pas verrouillées.

0 votes

Lorsque l'on fournit une liste d'arguments séparés par des espaces et entourés de guillemets pour qu'ils soient traités comme un seul et même argument, la fonction /c %~fnx0 %*' semble quitter toutes les parties sauf la première. Par exemple, de test.bat "arg1 arg2 arg3" seul arg1 est transmis en avant

0 votes

Il semble que, quoi qu'il arrive, le processus de démarrage supprime tous les guillemets dans la liste des arguments

0 votes

Ça marche pour moi ! Je l'utilise pour netsh int set int %wifiname% Enable/Disable .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X