Esiste un modo semplice senza la necessità di utilizzare uno strumento esterno: funziona bene con Windows 7, 8, 8.1 e 10 ed è anche retrocompatibile (Windows XP non ha alcun controllo dell'account utente, quindi non è necessaria l'elevazione) in quanto caso lo script procede).
Dai un'occhiata a questo codice (mi sono ispirato al codice di NIronwolf pubblicato nel thread File batch - "Accesso negato" su Windows 7? ), Ma l'ho migliorato - nella mia versione non esiste alcuna directory creata e rimossa in verifica i privilegi di amministratore):
::::::::::::::::::::::::::::::::::::::::::::
:: 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
Lo script sfrutta il fatto che NET FILE
richiede il privilegio di amministratore e restituisce errorlevel 1
se non lo possiedi. L'elevazione si ottiene creando uno script che riavvia il file batch per ottenere i privilegi. In questo modo Windows presenta la finestra di dialogo Controllo account utente e richiede l'account e la password dell'amministratore.
L'ho provato con Windows 7, 8, 8.1, 10 e con Windows XP - funziona bene per tutti. Il vantaggio è che, dopo il punto di partenza, è possibile inserire qualsiasi cosa che richieda i privilegi di amministratore di sistema, ad esempio, se si intende reinstallare e rieseguire un servizio Windows per scopi di debug (si presuppone che mypackage.msi sia un pacchetto di installazione del servizio) :
msiexec /passive /x mypackage.msi
msiexec /passive /i mypackage.msi
net start myservice
Senza questo privilegio che eleva lo script, Controllo dell'account utente ti richiederebbe tre volte il nome utente e la password dell'amministratore: ora ti verrà chiesto solo una volta all'inizio e solo se necessario.
Se il tuo script deve solo mostrare un messaggio di errore ed uscire se non ci sono privilegi di amministratore invece di elevazione automatica, questo è ancora più semplice: puoi farlo aggiungendo quanto segue all'inizio del tuo 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 ...
In questo modo, l'utente deve fare clic con il tasto destro e selezionare "Esegui come amministratore" . Lo script continuerà dopo l' REM
istruzione se rileva i diritti di amministratore, altrimenti esce con un errore. Se non è necessario il PAUSE
, basta rimuoverlo.
Importante: NET FILE [...] EXIT /D)
deve essere sulla stessa linea. Viene visualizzato qui in più righe per una migliore leggibilità!
Su alcune macchine, ho riscontrato problemi, che sono già stati risolti nella nuova versione precedente. Uno era dovuto alla diversa gestione delle virgolette doppie e l'altro era dovuto al fatto che UAC era disabilitato (impostato al livello più basso) su un computer Windows 7, quindi lo script si chiama più e più volte.
Ho risolto questo problema rimuovendo le virgolette nel percorso e ri-aggiungendole in seguito, e ho aggiunto un parametro aggiuntivo che viene aggiunto quando lo script si riavvia con diritti elevati.
Le doppie virgolette vengono rimosse da quanto segue (i dettagli sono qui ):
setlocal DisableDelayedExpansion
set "batchPath=%~0"
setlocal EnableDelayedExpansion
È quindi possibile accedere al percorso utilizzando !batchPath!
. Non contiene virgolette doppie, quindi è sicuro dirlo "!batchPath!"
più avanti nello script.
La linea
if '%1'=='ELEV' (shift & goto gotPrivileges)
controlla se lo script è già stato chiamato dallo script VBScript per elevare i diritti, evitando quindi ricorsioni infinite. Rimuove il parametro usando shift
.
Aggiornare:
Per evitare di dover registrare l' .vbs
estensione di Windows 10 , ho sostituito la linea
"%temp%\OEgetPrivileges.vbs"
dalla
"%SystemRoot%\System32\WScript.exe" "%temp%\OEgetPrivileges.vbs"
nello script di cui sopra; aggiunto anche cd /d %~dp0
come suggerito da Stephen (risposta separata) e da Tomáš Zato (commento) per impostare la directory di script come predefinita.
Ora lo script rispetta i parametri della riga di comando che gli vengono passati. Grazie a jxmallet, TanisDLJ e Peter Mortensen per osservazioni e ispirazioni.
Secondo il suggerimento di Artjom B., l'ho analizzato e sostituito SHIFT
da SHIFT /1
, che conserva il nome del file per il %0
parametro
Aggiunto del "%temp%\OEgetPrivileges_%batchName%.vbs"
alla :gotPrivileges
sezione per ripulire (come suggerito da mlt ). Aggiunto %batchName%
per evitare l'impatto se si eseguono diversi batch in parallelo. Si noti che è necessario utilizzare for
per poter sfruttare le funzioni di stringa avanzate, ad esempio %%~nk
, che estrae solo il nome file.
Struttura dello script ottimizzata, miglioramenti (aggiunta variabile a vbsGetPrivileges
cui ora si fa riferimento ovunque che consente di modificare facilmente il percorso o il nome del file, eliminare il .vbs
file solo se il batch doveva essere elevato)
In alcuni casi, era necessaria una diversa sintassi di chiamata per l'elevazione. Se lo script non funziona, controlla i seguenti parametri:
set cmdInvoke=0
set winSysFolder=System32
Cambia il primo parametro in set cmdInvoke=1
e verifica se il problema è già stato risolto. Si aggiungerà cmd.exe
allo script eseguendo l'elevazione.
Oppure prova a cambiare il secondo parametro in winSysFolder=Sysnative
, questo potrebbe aiutare (ma nella maggior parte dei casi non è richiesto) su sistemi a 64 bit. (ADBailey ha segnalato questo). "Sysnative" è richiesto solo per l'avvio di applicazioni a 64 bit da un host di script a 32 bit (ad es. Un processo di compilazione di Visual Studio o invocazione di script da un'altra applicazione a 32 bit).
Per rendere più chiaro il modo in cui i parametri vengono interpretati, ora lo sto visualizzando P1=value1 P2=value2 ... P9=value9
. Ciò è particolarmente utile se è necessario racchiudere parametri come percorsi tra virgolette doppie, ad es "C:\Program Files"
.
Se si desidera eseguire il debug dello script VBS, è possibile aggiungere il //X
parametro a WScript.exe come primo parametro, come suggerito qui (è descritto per CScript.exe, ma funziona anche per WScript.exe).
Link utili: