Come posso elevare automaticamente il mio file batch, in modo che possa richiedere i diritti di amministratore UAC se necessario?


209

Voglio che il mio file batch funzioni solo in modo elevato. Se non elevato, fornire all'utente la possibilità di riavviare il batch come elevato.

Sto scrivendo un file batch per impostare una variabile di sistema, copiare due file in un percorso di Programmi e avviare un programma di installazione del driver. Se un utente di Windows 7 / Windows Vista ( UAC abilitato e anche se si tratta di un amministratore locale) lo esegue senza fare clic con il pulsante destro del mouse e selezionando "Esegui come amministratore", otterrà "Accesso negato" copiando i due file e scrivendo la variabile di sistema .

Vorrei utilizzare un comando per riavviare automaticamente il batch come elevato se l'utente è in realtà un amministratore. Altrimenti, se non sono amministratori, voglio dire loro che hanno bisogno dei privilegi di amministratore per eseguire il file batch. Sto usando xcopy per copiare i file e REG ADD per scrivere la variabile di sistema. Sto usando quei comandi per gestire possibili macchine Windows XP. Ho trovato domande simili su questo argomento, ma nulla che riguarda il riavvio di un file batch come elevato.


2
Dai un'occhiata a ciò che ho pubblicato: non hai bisogno di alcuno strumento esterno, lo script controlla automaticamente i diritti di amministratore e si eleva automaticamente, se necessario.
Matt

1
Per favore, considera se la risposta di Matt sarebbe quella selezionata? Mi sembra così.
akauppi


Si prega di considerare i nuovi suggerimenti di Windows 10 nella sezione commenti dello script batch che ho pubblicato.
Matt,

4
Da cmd: @powershell Start-Process cmd -Verb runas. Da Powershell basta rilasciarlo @powershell. Questo inizia cmd con diritti elevati.
BrunoLM

Risposte:


20

Puoi fare in modo che lo script si chiami da solo con l' opzione psexec-h per eseguire l'elevazione.

Non sono sicuro di come potresti rilevare se è già in esecuzione come elevato o no ... forse riprovare con permanenti elevati solo se si verifica un errore Accesso negato?

Oppure, potresti semplicemente avere i comandi per xcopye reg.exeessere sempre eseguito con psexec -h, ma sarebbe fastidioso per l'utente finale se hanno bisogno di inserire la password ogni volta (o insicuro se hai incluso la password nello script) ...


10
Grazie per la risposta. Sfortunatamente, non penso di poter usare qualsiasi cosa al di fuori degli strumenti di Windows Vista / 7 di serie perché questo sarà destinato ai clienti fuori dal mio ufficio. Non credo di poter distribuire legalmente PSExec.
PDixon724,

2
Sì, penso che tu abbia ragione su questo - anche se PSExec è ora uno strumento Microsoft (da quando hanno acquistato i ragazzi di Sysinternals!) L'EULA proibisce la distribuzione :(
ewall

2
Penso che le mie opzioni siano piuttosto limitate. Se sapessi come codificare in VB, potrei renderlo un exe con un manifest admin, ma non saprei nemmeno da dove cominciare. Immagino che avvertirò all'inizio del batch l'esecuzione come amministratore se eseguono Windows Vista / 7. Ringrazia tutti.
PDixon724,

1
Un altro strumento di terze parti che potrebbe essere liberamente ridistribuibile e facile da integrare e apprendere è AutoIt ; questa pagina mostra come lo script richiede privilegi elevati.
ewall,

4
psexec -hnon funziona: "Impossibile installare il servizio PSEXESVC: accesso negato.". Devi avere già i diritti di amministratore per eseguire psexec.
Nicolas

319

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 FILErichiede il privilegio di amministratore e restituisce errorlevel 1se 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' REMistruzione 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' .vbsestensione 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 %~dp0come 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 SHIFTda SHIFT /1, che conserva il nome del file per il %0parametro

  • Aggiunto del "%temp%\OEgetPrivileges_%batchName%.vbs"alla :gotPrivilegessezione per ripulire (come suggerito da mlt ). Aggiunto %batchName%per evitare l'impatto se si eseguono diversi batch in parallelo. Si noti che è necessario utilizzare forper poter sfruttare le funzioni di stringa avanzate, ad esempio %%~nk, che estrae solo il nome file.

  • Struttura dello script ottimizzata, miglioramenti (aggiunta variabile a vbsGetPrivilegescui ora si fa riferimento ovunque che consente di modificare facilmente il percorso o il nome del file, eliminare il .vbsfile 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=1e verifica se il problema è già stato risolto. Si aggiungerà cmd.exeallo 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 //Xparametro a WScript.exe come primo parametro, come suggerito qui (è descritto per CScript.exe, ma funziona anche per WScript.exe).

Link utili:


9
Ottima risposta, anche se mi stupisce leggermente che tu debba fare tutto questo per fare qualcosa che è chiaramente necessario in alcuni casi.
jcoder il

50
In effetti, un comando come ELEVATE manca chiaramente nella lingua batch di Windows.
Matt,

2
Forse è più facile con PowerShell che sembra essere la lanaguge di scripting approvata per cose più complesse, ma non mi sono mai
preso la

1
La sintassi in powershell è completamente diversa (sintassi verbo-sostantivo), ma consente di chiamare facilmente gli assembly .NET. Ma è un po 'più difficile gestirlo (firma degli script, ecc.).
Matt,

2
@Matt Puoi verificare se c'è qualche verità dietro questa modifica rifiutata nella tua risposta?
Artjom B.

41

Come menzionato da jcoder e Matt, PowerShell ha reso tutto più semplice e potrebbe persino essere incorporato nello script batch senza creare un nuovo script.

Ho modificato la sceneggiatura di 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
Hai ragione, se PowerShell è installato, puoi usarlo per eseguire il file batch con elevazione (grazie per lo snippet di codice!). E sì, l'etichetta non è necessaria. Grazie per i suggerimenti, vale un +1 ... :-)
Matt,

2
Se richiamato da cmd Powershell.exe non ha l'opzione -verb runas. Esiste se sei già in PowerShell.
Adil Hindistan,

1
Mi piace molto questa soluzione, funziona benissimo per me. Su Windows 8.1 ho richiesto l'etichetta: gotPrivileges perché funzioni.
ShaunO

Sto riscontrando un problema se questo file batch è remoto su un percorso UNC.
Ryan Beesley,

Ho aggiunto la directory di modifica all'avvio, semplificato il flusso e pulito un po '. La WorkingDirectoryStart-Processrunas
directory di

28

Sto usando la risposta eccellente di Matt, ma vedo una differenza tra i miei sistemi Windows 7 e Windows 8 quando eseguo script elevati.

Una volta elevato lo script su Windows 8, la directory corrente è impostata su C:\Windows\system32. Fortunatamente, c'è una soluzione semplice cambiando la directory corrente nel percorso dello script corrente:

cd /d %~dp0

Nota: utilizzare cd /dper assicurarsi che anche la lettera dell'unità sia cambiata.

Per verificare ciò, è possibile copiare quanto segue in uno script. Esegui normalmente su entrambe le versioni per vedere lo stesso risultato. Esegui come amministratore e vedi la differenza in 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
Buon suggerimento, Stephen. Quindi lo script dovrebbe terminare cd %~dp0per mantenere il suo percorso attuale (suppongo che funzioni anche in Win7, quindi lo stesso comando può essere usato anche se necessario solo per Win8 +). +1 per questo!
Matt,

2
Da notare questo è stato richiesto anche sul mio sistema con Windows 7.
meh-uk

1
o usa pushd %~dp0invece ... perché? perchépopd
Jaroslav Záruba il

27

Lo faccio in questo modo:

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

In questo modo è semplice e usa solo i comandi predefiniti di Windows. È fantastico se devi ridistribuire il tuo file batch.

CD /d %~dp0Imposta la directory corrente sulla directory corrente del file (se non lo è già, indipendentemente dall'unità in cui si trova il file, grazie /dall'opzione).

%~nx0 Restituisce il nome file corrente con estensione (se non includi l'estensione e c'è un exe con lo stesso nome nella cartella, chiamerà exe).

Ci sono così tante risposte su questo post che non so nemmeno se la mia risposta sarà vista.

Comunque, trovo in questo modo più semplice rispetto alle altre soluzioni proposte sulle altre risposte, spero che aiuti qualcuno.


4
cd% ~ dp0 non funzionerà su unità di rete, utilizzare invece pushd% ~ dp0.
Stavm,

1
Adoro la semplicità di questa risposta. E infine un motivo per usare Jscript!
Joe Coder,

1
Magia! Grazie mille.
Daniele Orlando,

1
@ Lupo ho scritto una risposta enorme solo per rendermi conto di averti capito male ... Ho capito cosa intendi ora. Lo modificherò per includere il /d. Grazie amico :) (PS: anche qui pianista!)
Matheus Rocha,

1
Funziona alla grande, ma potrebbe essere una buona idea spostare il cdcomando all'inizio (questo assicura che il percorso sia disponibile anche per lo script elevato, altrimenti lo script elevato viene eseguito da system32). Dovresti anche reindirizzare il comando net su nul per nasconderne l'output:net session >nul 2>&1
Nulano

23

Matt ha un'ottima risposta, ma elimina qualsiasi argomento passato alla sceneggiatura. Ecco la mia modifica che mantiene gli argomenti. Ho anche incorporato la correzione di Stephen per il problema della directory di lavoro in 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...

1
Questa è una risposta utile Tuttavia, in ECHO UAC.ShellExecute....linea, "batchArgs!"non espanderà la variabile. Usa "!batchArgs!". La mia modifica è stata rifiutata, quindi commento.
Cipolla volante

1
@fliedonion ben notato! Non sono sicuro del motivo per cui la tua modifica è stata rifiutata perché era sicuramente un errore di battitura e la tua correzione funziona. Ho apportato personalmente la modifica e l'ho testata su Win 8.1. Ora per trovare tutti gli script in cui uso questo codice ....
jxmallett,

2
Lo script si è rotto durante l'utilizzo di argomenti tra virgolette, come test.bat "a thing"o "test script.bat" arg1 arg2. Tutto risolto ora.
jxmallett,

Sono riuscito a romperlo (per colpa mia: eseguire script dall'unità di rete mappata, poiché admin e l'utente normale non hanno lo stesso mapping). Ancora: c'è un modo per vedere l'output? Per me, ho dovuto trovare .vbs e cambiare / c in a / K e poi vederlo manualmente.
Andreas Reiff,

21

Uso PowerShell per riavviare lo script elevato se non lo è. Metti queste righe in cima alla tua sceneggiatura.

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

Ho copiato il metodo "net name" dalla risposta di @ Matt. La sua risposta è molto meglio documentata e ha messaggi di errore e simili. Questo ha il vantaggio che PowerShell è già installato e disponibile su Windows 7 e versioni successive. Nessun file VBScript temporaneo (* .vbs) e non è necessario scaricare strumenti.

Questo metodo dovrebbe funzionare senza alcuna configurazione o impostazione, a condizione che le autorizzazioni di esecuzione di PowerShell non siano bloccate.


quando si fornisce un elenco di argomenti separati da spazi bianchi racchiusi tra virgolette per farlo trattare come uno, la /c %~fnx0 %*'parte sembra lasciare ogni parte oltre alla prima. Ad esempio, test.bat "arg1 arg2 arg3"viene trasmesso solo arg1
Nicolas Mommaerts,

Sembra che, indipendentemente da cosa, il processo di avvio rimuove tutte le doppie virgolette nell'elenco degli argomenti.
Nicolas Mommaerts,

Per me va bene! Lo sto usando per netsh int set int %wifiname% Enable/Disable.
Marslo,

2
Ho avuto lo stesso problema di Nicolas Mommaerts sopra. Non capisco perché funzioni (il miglior tipo di correzione), ma quanto segue funziona come dovrebbe (notare tutte le virgolette alla fine): net file 1>nul 2>nul && goto :run || powershell -ex unrestricted -Command "Start-Process -Verb RunAs -FilePath '%comspec%' -ArgumentList '/c ""%~fnx0""""'"
terremoti

Un altro problema (inconveniente) è che lo script viene messo in pausa (attende l'input dell'utente) se il servizio del server non è in esecuzione (l'ho disabilitato per motivi). Di solito collaudo i permessi di amministratore cercando di scrivere nel percorso del file HOSTS , ma forse è meglio invocare il comando powershell -Verb runas , invece di fare affidamento su servizi Windows abilitati o tentare di scrivere file.
script'n'code,

15

Per alcuni programmi che impostano la __COMPAT_LAYERvariabile d'ambiente super segreta su RunAsInvoker funzionerà. Controlla questo:

set "__COMPAT_LAYER=RunAsInvoker"
start regedit.exe

Sebbene in questo modo non ci sarà alcun controllo dell'account utente che continuerà senza le autorizzazioni di amministratore.


1
Il collegamento al sito Microsoft non ha più funzionato, quindi l'ho modificato con il contenuto su archive.org. Se qualcuno riesce a trovare un link funzionante al contenuto sul sito di Microsoft, ma in ogni caso, si prega di aggiornarlo a quello.
RockPaperLizard

1
è ancora con integrità media non elevata , quindi non è possibile modificare HKLM in regedit. Ha appena saltato l'UAC.
HackingAddict1337

5

L'ho incollato all'inizio della sceneggiatura:

:: 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"
:--------------------------------------

2
Mi piace l'elaborazione arg nella tua sceneggiatura. Si noti che caclsè obsoleto in Windows 7 e versioni più recenti di Windows.
Matt,

Fsutil dirty è ancora meglio
Wolf

1
Sai che la riga pushd "%CD%"salva la directory di lavoro corrente e passa alla directory di lavoro corrente?
Lupo,

3

Ho scritto gsudo, a sudofor windows : che si eleva nella console corrente (nessun contesto passa a una nuova finestra), con una cache delle credenziali (popup UAC ridotti) e eleva anche i comandi di PowerShell .

Permette di elevare i comandi che richiedono i privilegi di amministratore, o l'intero batch, se lo si desidera. Basta anteporregsudo prima di tutto ciò che deve essere eseguito elevato.

Esempio di file batch che si eleva usando gsudo:

EDIT: nuova versione di una fodera che funziona con qualsiasi linguaggio di Windows ed evita problemi di whoami :

net session >nul 2>nul & net session >nul 2>nul || gsudo "%~f0" && exit /b || exit /b
:: This will run as admin ::

Alternativa (versione originale):

@echo off
  rem Test if current context is already elevated:
  whoami /groups | findstr /b BUILTIN\Administrators | findstr /c:"Enabled group" 1> nul 2>nul && goto :isadministrator
  echo You are not admin. (yet)
  :: Use gsudo to launch this batch file elevated.
  gsudo "%~f0"
  goto end
:isadministrator
  echo You are admin.
  echo (Do admin stuff now).
:end

Installare:

Guarda gsudo in azione: demo gsudo


Freddo. Grazie. Su quali versioni di Windows funziona?
RockPaperLizard

La suite di test funziona su Server 2019 e la mia casella di sviluppo locale è Windows 10 1909. Spiacenti, non ho testato la compatibilità con altri sistemi operativi precedenti.
Gerardo Grignoli,

Grazie Gerardo. Se qualcuno lo prova su altre versioni di Windows, pubblica i risultati.
RockPaperLizard

Ho appena testato gsudo v0.7 su Windows 8.1 e ha funzionato. Non è banale installarlo .Net Framework 4.6lì. Fortunatamente ha choco install dotnet4.6.2portato alcune dipendenze difficili da ottenere. Quindi gsudo config Prompt "$p# "risolto un problema con la ConHostvisualizzazione di un prompt errato (caratteri di sequenza di escape invece del carattere rosso). @RockPaperLizard
Gerardo Grignoli,

Grazie mille Gerardo. Potrebbe essere ricompilato per funzionare con qualsiasi versione di .Net Framework precedente alla 4.6 o dipende da alcune funzionalità specifiche della 4.6?
RockPaperLizard,

2

Sebbene non sia direttamente applicabile a questa domanda, poiché desidera alcune informazioni per l'utente, google mi ha portato qui quando volevo eseguire il mio file .bat elevato dall'utilità di pianificazione.

L'approccio più semplice è stato quello di creare un collegamento al file .bat, perché per un collegamento è possibile impostare Run as administrator direttamente dalle proprietà avanzate.

Eseguendo il collegamento dall'utilità di pianificazione, viene eseguito il file .bat elevato.


1

Se non è necessario passare argomenti, ecco uno script di prompt UAC compatto lungo una sola riga. Questo fa una cosa simile allo script di elevazione nella risposta più votata, ma non passa attraverso gli argomenti poiché non esiste un modo infallibile per farlo che gestisca ogni possibile combinazione di personaggi velenosi.

@echo off
net sess>nul 2>&1||(echo(CreateObject("Shell.Application"^).ShellExecute"%~0",,,"RunAs",1:CreateObject("Scripting.FileSystemObject"^).DeleteFile(wsh.ScriptFullName^)>"%temp%\%~nx0.vbs"&start wscript.exe "%temp%\%~nx0.vbs"&exit)

:: Your batch file goes here

0

Utilizzando PowerShell.

Se il file cmd è lungo, ne uso uno per richiedere l'elevazione, quindi chiamo quello che fa il lavoro effettivo.

Se lo script è un semplice comando, tutto può rientrare in un file cmd. Non dimenticare di includere il percorso nei file di script.

Modello:

@echo off
powershell -Command "Start-Process 'cmd' -Verb RunAs -ArgumentList '/c " comands or another script.cmd go here "'"

Esempio 1:

@echo off
powershell -Command "Start-Process 'cmd' -Verb RunAs -ArgumentList '/c "powershell.exe -NoProfile -ExecutionPolicy Bypass -File C:\BIN\x.ps1"'"

Esempio 2:

@echo off
powershell -Command "Start-Process 'cmd' -Verb RunAs -ArgumentList '/c "c:\bin\myScript.cmd"'"

0

Prova questo:

@echo off
CLS
: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 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)
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

Se hai bisogno di informazioni su quel file batch, esegui lo snippet HTML / JS / CSS:

document.getElementsByTagName("data")[0].innerHTML="ElevateBatch, version 4, release<br>Required Commands:<ul><li>CLS</li><li>SETLOCAL</li><li>SET</li><li>FOR</li><li>NET</li><li>IF</li><li>ECHO</li><li>GOTO</li><li>EXIT</li><li>DEL</li></ul>It auto-elevates the system and if the user presses No, it just doesn't do anything.<br>This CANNOT be used to create an Elevated Explorer.";
data{font-family:arial;text-decoration:none}
<data></data>


-3

La seguente soluzione è pulita e funziona perfettamente.

  1. Scarica il file zip Elevate da https://www.winability.com/download/Elevate.zip

  2. All'interno di zip dovresti trovare due file: Elevate.exe ed Elevate64.exe. (Quest'ultima è una compilazione nativa a 64 bit, se è necessario che, sebbene la normale versione a 32 bit, Elevate.exe, funzioni correttamente con entrambe le versioni a 32 e 64 bit di Windows)

  3. Copia il file Elevate.exe in una cartella in cui Windows può sempre trovarlo (come C: / Windows). O meglio è possibile copiare nella stessa cartella in cui si prevede di conservare il file bat.

  4. Per usarlo in un file batch, basta anteporre il comando che si desidera eseguire come amministratore con il comando elevate, in questo modo:

 elevate net start service ...

2
Tale comando apre solo una finestra di dialogo che chiede all'utente se è possibile eseguire questo comando. Quindi non puoi usare questo comando in un file batch che dovrebbe essere eseguito SENZA interazioni dell'utente.
Radon8472,

Se fosse possibile elevare SENZA l'interazione dell'utente, sarebbe un enorme buco nella sicurezza, no? Ogni virus inizierebbe a utilizzare quel metodo per elevarsi senza l'approvazione dell'utente.
Andrei Belogortseff,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.