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 que surélevé. Si pas élevé, la possibilité pour l'utilisateur de relancer de lot élevé.

J'écris un fichier batch pour définir une variable système, copier deux fichiers dans un emplacement Program Files et démarrer un programme d'installation du pilote. Si un utilisateur Windows 7/Windows Vista (UAC activé 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 écriture de la variable système.

Je voudrais utiliser une commande pour redémarrer automatiquement le lot élevée si l'utilisateur est en fait un administrateur. Sinon, s'ils ne sont pas un administrateur, je veux leur dire qu'ils ont besoin de 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 faire face à d'éventuelles machines Windows XP. J'ai trouvé des questions similaires sur ce sujet, mais rien qui traite de la relance d'un fichier de lot élevé.

182
demandé sur Matt 2011-08-12 22:55:13

10 réponses

Vous pouvez faire appeler le script lui-même avec l'option psexec -h pour exécuter elevated.

Je ne suis pas sûr de savoir comment détecter s'il fonctionne déjà comme élevé ou non... peut-être réessayer avec des perms élevés seulement s'il y a une erreur D'Accès refusé?

Ou, vous pourriez simplement avoir les commandes pour le xcopy et reg.exe toujours être exécuté avec psexec -h, mais il serait ennuyeux pour l'utilisateur final s'il a besoin d'entrer son mot de passe à chaque fois (ou non sécurisé si vous avez inclus le mot de passe dans le script)...

19
répondu ewall 2011-08-12 19:04:29

Il existe un moyen facile 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-dans ce cas, le script ne fait que commencer).

Consultez ce code (j'ai été inspiré par le code de NIronwolf posté dans le fil fichier Batch- "Accès refusé" 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
::::::::::::::::::::::::::::::::::::::::::::
 @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 profite du fait que NET FILE nécessite le privilège administrateur et renvoie errorlevel 1 Si vous ne l'avez pas. L'élévation est obtenue en créant un script qui relance le fichier batch pour obtenir des privilèges. Cela fait que Windows présente 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 avec Windows XP-cela fonctionne très bien pour tout. L'avantage est, 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 relancer un service Windows à des fins de débogage (supposé 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, UAC vous demanderait trois fois votre utilisateur administrateur et votre mot de passe-maintenant vous n'êtes demandé qu'une seule fois au début, et seulement 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 de auto-élévation, 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 faire un clic droit et sélectionner "Exécuter en tant qu'administrateur". Le script continuera après l'instruction REM s'il détecte les droits d'administrateur, sinon quittez avec une erreur. Si vous n'avez pas besoin du PAUSE, supprimez simplement il. Important: NET FILE [...] EXIT /D) doit être sur la même ligne. Il est affiché ici en 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 dépouillant les citations dans le chemin et les rajouter plus tard, et j'ai ajouté un paramètre supplémentaire qui est ajouté lorsque le script redémarre avec des droits élevés.

Les guillemets doubles sont supprimés par ce qui suit (les détails sont ici):

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

Vous pouvez ensuite accéder au chemin en utilisant !batchPath!. Il ne contient pas de guillemets doubles, il est donc prudent 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 VBScript script pour élever les droits, évitant ainsi les récursions sans fin. Il supprime le paramètre en utilisant shift.


Mise à Jour:

  • Pour éviter d'avoir à s'inscrire à l' .vbs extension 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 honneurs les paramètres de ligne de commande 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 j'ai remplacé SHIFT par SHIFT /1, qui conserve le nom du fichier pour le paramètre %0

  • Ajouté del "%temp%\OEgetPrivileges_%batchName%.vbs" de la :gotPrivileges section pour nettoyer (comme mlt suggéré). Ajouté %batchName% pour éviter tout impact si vous exécutez différents lots en parallèle. Notez que vous devez utiliser for pour être capable de tirer parti 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 maintenant référencée partout permettant de changer facilement le chemin ou le nom du fichier, supprimer uniquement le fichier .vbs si le lot doit ê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 ce qui suit paramètres:
    set cmdInvoke=0
    set winSysFolder=System32
    Changez le 1er paramètre en set cmdInvoke=1 et vérifiez si cela résout déjà le problème. Il ajoutera cmd.exe au script effectuant l'élévation.
    Ou essayez de changer le 2ème paramètre en winSysFolder=Sysnative, cela peut aider (mais n'est dans la plupart des cas pas nécessaire) sur les systèmes 64 bits. (ADBailey a signalé cela). "Sysnative" n'est requis que pour le lancement d'applications 64 bits à partir d'un hôte de script 32 bits (par exemple, un processus de construction Visual Studio ou une autre application 32 bits).

  • Pour rendre plus clair comment les paramètres sont interprétés, Je l'affiche maintenant comme P1=value1 P2=value2 ... P9=value9. Ceci est particulièrement utile si vous devez entourer des paramètres comme les chemins entre guillemets doubles, par exemple "C:\Program Files".

295
répondu Matt 2018-06-20 07:14:10

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

J'ai modifié le script de Matt:

:checkPrivileges 
NET FILE 1>NUL 2>NUL
if '%errorlevel%' == '0' ( goto gotPrivileges 
) else ( powershell "saps -filepath %0 -verb runas" >nul 2>&1)
exit /b 

Il n'y a pas besoin de l'Étiquette :getPrivileges.

29
répondu Ir Relevant 2014-12-29 23:47:12

J'utilise L'excellente réponse de Matt, mais je vois 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é sur Windows 8, le répertoire courant est défini sur C:\Windows\system32. Heureusement, il existe une solution de contournement facile en changeant le répertoire courant sur le chemin du script courant:

cd /d %~dp0

Remarque: Utilisez cd /d pour vous assurer que la lettre de lecteur est également modifiée.

Pour tester cela, vous pouvez copier ce qui suit dans un script. Exécuter normalement sur les deux versions pour voir le même résultat. Exécutez en tant Qu'administrateur et voyez la différence dans 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
27
répondu Stephen Klancher 2017-02-08 12:07:28

Je le fais de cette façon:

NET SESSION
IF %ERRORLEVEL% NEQ 0 GOTO ELEVATE
GOTO ADMINTASKS

:ELEVATE
CD /d %~dp0
MSHTA "javascript: var shell = new ActiveXObject('shell.application'); shell.ShellExecute('%~nx0', '', '', 'runas', 1);close();"
EXIT

:ADMINTASKS
(Do whatever you need to do here)
EXIT

De cette façon, c'est simple et utilisez uniquement les commandes par défaut de windows. C'est génial si vous avez besoin de redistribuer votre fichier batch.

CD /d %~dp0 définit le répertoire courant sur le répertoire courant du fichier (s'il ne l'est pas déjà, quel que soit le lecteur dans lequel se trouve le fichier, grâce à l'option /d).

%~nx0 retourne le nom de fichier actuel avec l'extension (Si vous n'incluez pas l'extension et qu'il y a un exe avec le même nom sur le dossier, il appellera EXE).

Il y a tellement de réponses sur ce post que je ne sais même pas si ma réponse sera vue.

Quoi qu'il en soit, je trouve cette façon plus simple que les autres solutions proposées sur les autres réponses, j'espère que cela aide quelqu'un.

24
répondu Matheus Rocha 2017-02-13 13:50:25

Matt a une excellente réponse, mais il supprime tous les arguments passés au script. Voici ma modification qui garde des arguments. J'ai également incorporé le correctif de Stephen pour le problème du répertoire de travail dans Windows 8.

@ECHO OFF
setlocal EnableDelayedExpansion

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

:getPrivileges
if '%1'=='ELEV' ( goto START )

set "batchPath=%~f0"
set "batchArgs=ELEV"

::Add quotes to the batch path, if needed
set "script=%0"
set script=%script:"=%
IF '%0'=='!script!' ( GOTO PathQuotesDone )
    set "batchPath=""%batchPath%"""
:PathQuotesDone

::Add quotes to the arguments, if needed.
:ArgLoop
IF '%1'=='' ( GOTO EndArgLoop ) else ( GOTO AddArg )
    :AddArg
    set "arg=%1"
    set arg=%arg:"=%
    IF '%1'=='!arg!' ( GOTO NoQuotes )
        set "batchArgs=%batchArgs% "%1""
        GOTO QuotesDone
        :NoQuotes
        set "batchArgs=%batchArgs% %1"
    :QuotesDone
    shift
    GOTO ArgLoop
:EndArgLoop

::Create and run the vb script to elevate the batch file
ECHO Set UAC = CreateObject^("Shell.Application"^) > "%temp%\OEgetPrivileges.vbs"
ECHO UAC.ShellExecute "cmd", "/c ""!batchPath! !batchArgs!""", "", "runas", 1 >> "%temp%\OEgetPrivileges.vbs"
"%temp%\OEgetPrivileges.vbs" 
exit /B

:START
::Remove the elevation tag and set the correct working directory
IF '%1'=='ELEV' ( shift /1 )
cd /d %~dp0

::Do your adminy thing here...
19
répondu jxmallett 2015-04-07 00:57:57

J'utilise PowerShell pour relancer le script élevé si ce n'est pas le cas. Mettre 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 beaucoup mieux documentée et a des messages d'erreur et autres. Celui-ci a l'avantage que PowerShell est déjà installé et disponible sur Windows 7. Pas de VBScript temporaire (*.VBS), et vous n'avez pas besoin de télécharger des outils.

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

16
répondu Ryan Bemrose 2014-12-29 23:52:05

Pour certains programmes, définir la variable d'environnement super secret __COMPAT_LAYER sur RunAsInvoker fonctionne .Vérifiez ceci:

set "__COMPAT_LAYER=RunAsInvoker"
start regedit.exe

Bien que comme ça, il n'y aura pas D'UAC invitant l'utilisateur à continuer sans autorisations d'administrateur.

12
répondu npocmaka 2016-03-31 09:11:04

J'ai collé ceci au début du script:

:: BatchGotAdmin
:-------------------------------------
REM  --> Check for permissions
>nul 2>&1 "%SYSTEMROOT%\system32\icacls.exe" "%SYSTEMROOT%\system32\config\system"

REM --> If error flag set, we do not have admin.
if '%errorlevel%' NEQ '0' (
    echo Requesting administrative privileges...
    goto UACPrompt
) else ( goto gotAdmin )

:UACPrompt
    echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
    echo args = "" >> "%temp%\getadmin.vbs"
    echo For Each strArg in WScript.Arguments >> "%temp%\getadmin.vbs"
    echo args = args ^& strArg ^& " "  >> "%temp%\getadmin.vbs"
    echo Next >> "%temp%\getadmin.vbs"
    echo UAC.ShellExecute "%~s0", args, "", "runas", 1 >> "%temp%\getadmin.vbs"

    "%temp%\getadmin.vbs" %*
    exit /B

:gotAdmin
    if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )
    pushd "%CD%"
    CD /D "%~dp0"
:--------------------------------------
5
répondu TanisDLJ 2015-10-23 16:51:51

La solution suivante est propre et fonctionne parfaitement.

  1. Télécharger Élever fichier zip à partir de https://www.winability.com/download/Elevate.zip

  2. Dans zip, vous devriez trouver deux fichiers: Elevate.exe et Elevate64.EXE. (Ce dernier est une compilation 64 bits native, si vous en avez besoin, bien que la version 32 bits régulière, Elevate.exe, devrait fonctionner correctement avec les versions 32 et 64 bits de Windows)

  3. Copiez le fichier Élever.exe dans un dossier où Windows peut toujours le trouver (comme C:/Windows). Ou mieux vous pouvez copier dans le même dossier où vous prévoyez de garder votre fichier bat.

  4. Pour l'utiliser dans un fichier batch, ajoutez simplement la commande que vous souhaitez exécuter en tant qu'administrateur avec la commande elevate, comme ceci:

 elevate net start service ...
0
répondu Vaibhav Jain 2018-09-24 17:29:12