it-swarm.com.de

Wie kann ich meine Batchdatei automatisch erhöhen, sodass sie bei Bedarf UAC-Administratorrechte anfordert?

Ich möchte, dass meine Batchdatei nur mit erhöhten Rechten ausgeführt wird. Wenn nicht erhöht, bieten Sie dem Benutzer die Möglichkeit, den Stapel als erhöht neu zu starten.

Ich schreibe eine Batch-Datei, um eine Systemvariable festzulegen, kopiere zwei Dateien an einen Speicherort Programme und starte ein Treiber-Installationsprogramm. Wenn ein Windows 7/Windows Vista-Benutzer ( UAC aktiviert ist und selbst wenn er ein lokaler Administrator ist), wird er ausgeführt, ohne mit der rechten Maustaste darauf zu klicken und "Als Administrator ausführen" auszuwählen. wird ihnen der Zugriff verweigert, wenn sie die beiden Dateien kopieren und die Systemvariable schreiben.

Ich möchte einen Befehl verwenden, um den Stapel automatisch als erhöht neu zu starten, wenn der Benutzer tatsächlich ein Administrator ist. Andernfalls möchte ich ihnen mitteilen, dass sie Administratorrechte benötigen, um die Batch-Datei auszuführen, wenn sie kein Administrator sind. Ich benutze xcopy zum Kopieren der Dateien und REG ADD zum Schreiben die Systemvariable. Ich benutze diese Befehle, um mit möglichen Windows XP-Computern umzugehen. Ich habe ähnliche Fragen zu diesem Thema gefunden, aber nichts, was sich mit dem Neustart einer Stapeldatei als erhöht befasst.

194
PDixon724

Sie können das Skript mit der Option psexec-h Aufrufen lassen, damit es mit erhöhten Rechten ausgeführt wird.

Ich bin mir nicht sicher, wie Sie erkennen würden, ob es bereits als erhöht ausgeführt wird oder nicht. Versuchen Sie es möglicherweise erneut mit erhöhten Berechtigungen, nur wenn ein Fehler "Zugriff verweigert" vorliegt.

Oder Sie könnten einfach die Befehle für xcopy und reg.exe Immer mit psexec -h Ausführen lassen, aber es wäre für den Endbenutzer ärgerlich, wenn er sie eingeben müsste Passwort jedes Mal (oder unsicher, wenn Sie das Passwort in das Skript aufgenommen haben) ...

20
ewall

Es gibt eine einfache Möglichkeit, ohne ein externes Tool zu verwenden - es läuft problemlos unter Windows 7, 8, 8.1 und 10 und ist auch abwärtskompatibel (Windows XP hat keine Benutzerkontensteuerung, daher ist keine Erhöhung erforderlich. In diesem Fall wird das Skript einfach fortgesetzt.).

Schauen Sie sich diesen Code an (ich war inspiriert von dem Code von NIronwolf, der im Thread veröffentlicht wurde Batchdatei - "Zugriff verweigert" unter Windows 7? ), aber ich habe verbessert - in meiner Version wurde kein Verzeichnis erstellt und entfernt, um nach Administratorrechten zu suchen):

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

Das Skript nutzt die Tatsache aus, dass NET FILE Administratorrechte erfordert und gibt errorlevel 1 Zurück, wenn Sie es nicht haben . Die Erhöhung wird durch Erstellen eines Skripts erreicht, das die Batchdatei neu startet, um Berechtigungen zu erhalten. Dies führt dazu, dass Windows das Dialogfeld "Benutzerkontensteuerung" anzeigt und Sie nach dem Administrator-Konto und dem Kennwort fragt.

Ich habe es mit Windows 7, 8, 8.1, 10 und mit Windows XP getestet - es funktioniert einwandfrei für alle. Der Vorteil ist, dass Sie nach dem Startpunkt alle Elemente platzieren können, für die Systemadministratorrechte erforderlich sind, z. B. wenn Sie einen Windows-Dienst zu Debugzwecken erneut installieren und ausführen möchten (vorausgesetzt, mypackage.msi ist ein Dienstinstallationspaket). :

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

Ohne dieses Skript zur Erhöhung der Berechtigungen werden Sie von der Benutzerkontensteuerung dreimal nach Ihrem Administratorbenutzer und Kennwort gefragt. Jetzt werden Sie zu Beginn nur noch einmal und nur bei Bedarf gefragt.


Wenn Ihr Skript nur eine Fehlermeldung anzeigen und beenden muss, wenn keine Administratorrechte vorhanden sind, anstatt automatisch zu erhöhen, ist dies noch einfacher: Sie Um dies zu erreichen, fügen Sie am Anfang Ihres Skripts Folgendes hinzu:

@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 ...

Auf diese Weise muss der Benutzer mit der rechten Maustaste klicken und "Als Administrator ausführen" auswählen. Das Skript wird nach der Anweisung REM fortgesetzt, wenn es Administratorrechte erkennt, andernfalls wird es mit einem Fehler beendet. Wenn Sie das PAUSE nicht benötigen, entfernen Sie es einfach. Wichtig: NET FILE [...] EXIT /D) Muss in derselben Zeile stehen. Es wird hier zur besseren Lesbarkeit mehrzeilig dargestellt!


Auf einigen Rechnern sind Probleme aufgetreten, die in der obigen neuen Version bereits behoben sind. Einer war auf die unterschiedliche Behandlung von doppelten Anführungszeichen zurückzuführen, und der andere Grund war die Tatsache, dass die Benutzerkontensteuerung auf einem Windows 7-Computer deaktiviert (auf die niedrigste Stufe eingestellt) war. Daher ruft sich das Skript immer wieder von selbst auf.

Ich habe dies jetzt behoben, indem ich die Anführungszeichen im Pfad entfernt und später wieder hinzugefügt habe, und ich habe einen zusätzlichen Parameter hinzugefügt, der hinzugefügt wird, wenn das Skript mit erhöhten Rechten neu gestartet wird.

Die doppelten Anführungszeichen werden wie folgt entfernt (Details sind hier ):

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

Sie können dann mit !batchPath! Auf den Pfad zugreifen. Es enthält keine doppelten Anführungszeichen, daher kann man später im Skript sicher "!batchPath!" Sagen.

Die Linie

if '%1'=='ELEV' (shift & goto gotPrivileges)

prüft, ob das Skript bereits vom Skript VBScript aufgerufen wurde, um die Rechte zu erhöhen und somit endlose Rekursionen zu vermeiden. Der Parameter wird mit shift entfernt.


Update:

  • Um zu vermeiden, dass die Erweiterung .vbs In Windows 10 registriert werden muss, habe ich die Zeile ersetzt
    "%temp%\OEgetPrivileges.vbs"
    durch
    "%SystemRoot%\System32\WScript.exe" "%temp%\OEgetPrivileges.vbs"
    im obigen Skript; fügte auch cd /d %~dp0 hinzu, wie von Stephen (separate Antwort) und Tomáš Zato (Kommentar) vorgeschlagen, um das Skriptverzeichnis als Standard festzulegen.

  • Jetzt berücksichtigt das Skript Befehlszeilenparameter, die an es übergeben werden. Vielen Dank an jxmallet, TanisDLJ und Peter Mortensen für Beobachtungen und Inspirationen.

  • Gemäß Artjom B.'s Hinweis habe ich es analysiert und SHIFT durch SHIFT /1 Ersetzt, wodurch der Dateiname für den Parameter %0 Erhalten bleibt

  • del "%temp%\OEgetPrivileges_%batchName%.vbs" Wurde zum Abschnitt :gotPrivileges Hinzugefügt, um zu bereinigen (wie in mlt vorgeschlagen). %batchName% Hinzugefügt, um Auswirkungen zu vermeiden, wenn Sie verschiedene Chargen gleichzeitig ausführen. Beachten Sie, dass Sie for verwenden müssen, um die erweiterten Zeichenfolgenfunktionen wie %%~nk Nutzen zu können, mit denen nur der Dateiname extrahiert wird.

  • Optimierte Skriptstruktur, Verbesserungen (hinzugefügte Variable vbsGetPrivileges, auf die jetzt überall verwiesen wird, um den Pfad oder den Namen der Datei einfach zu ändern. Löschen Sie die Datei .vbs Nur, wenn der Stapel erhöht werden musste.)

  • In einigen Fällen war für die Erhöhung eine andere Aufrufsyntax erforderlich. Wenn das Skript nicht funktioniert, überprüfen Sie die folgenden Parameter:
    set cmdInvoke=0
    set winSysFolder=System32
    Ändern Sie entweder den 1. Parameter in set cmdInvoke=1 Und prüfen Sie, ob das Problem dadurch bereits behoben ist. Es wird dem Skript, das die Erhöhung durchführt, cmd.exe Hinzugefügt.
    Oder versuchen Sie, den 2. Parameter in winSysFolder=Sysnative Zu ändern. Dies könnte auf 64-Bit-Systemen hilfreich sein (ist aber in den meisten Fällen nicht erforderlich). (ADBailey hat dies gemeldet). "Sysnative" ist nur zum Starten von 64-Bit-Anwendungen von einem 32-Bit-Skripthost erforderlich (z. B. ein Visual Studio-Erstellungsprozess oder ein Skriptaufruf von einer anderen 32-Bit-Anwendung).

  • Um klarer zu machen, wie die Parameter interpretiert werden, zeige ich sie jetzt als P1=value1 P2=value2 ... P9=value9 An. Dies ist besonders nützlich, wenn Sie Parameter wie Pfade in doppelte Anführungszeichen setzen müssen, z. "C:\Program Files".

Nützliche Links:

306
Matt

Wie JCoder und Matt bereits erwähnt haben, hat PowerShell es einfach gemacht und es konnte sogar in das Stapelskript eingebettet werden, ohne ein neues Skript zu erstellen.

Ich habe Matts Skript geändert:

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

Es gibt keine Notwendigkeit für die :getPrivileges Etikette.

33
Ir Relevant

Ich verwende die ausgezeichnete Antwort von Matt, sehe jedoch einen Unterschied zwischen meinen Windows 7- und Windows 8-Systemen, wenn ich Skripts mit erhöhten Rechten ausführe.

Sobald das Skript unter Windows 8 aktiviert ist, wird das aktuelle Verzeichnis auf C:\Windows\system32 Gesetzt. Glücklicherweise gibt es eine einfache Problemumgehung, indem Sie das aktuelle Verzeichnis in den Pfad des aktuellen Skripts ändern:

cd /d %~dp0

Hinweis: Verwenden Sie cd /d, Um sicherzustellen, dass auch der Laufwerksbuchstabe geändert wird.

Um dies zu testen, können Sie Folgendes in ein Skript kopieren. Führen Sie beide Versionen normal aus, um dasselbe Ergebnis zu erhalten. Führen Sie als Administrator aus und sehen Sie den Unterschied 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
27

Ich mache es so:

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

Auf diese Weise ist es einfach und verwendet nur Windows-Standardbefehle. Es ist großartig, wenn Sie Ihre Batch-Datei neu verteilen müssen.

CD /d %~dp0 Setzt das aktuelle Verzeichnis auf das aktuelle Verzeichnis der Datei (falls noch nicht geschehen, unabhängig vom Laufwerk, in dem sich die Datei befindet, dank der Option /d).

%~nx0 Gibt den aktuellen Dateinamen mit der Erweiterung zurück (Wenn Sie die Erweiterung nicht angeben und eine Exe mit demselben Namen im Ordner vorhanden ist, wird die Exe aufgerufen).

Es gibt so viele Antworten auf diesen Beitrag, dass ich nicht einmal weiß, ob meine Antwort zu sehen sein wird.

Wie auch immer, ich finde diesen Weg einfacher als die anderen Lösungen, die für die anderen Antworten vorgeschlagen wurden. Ich hoffe, es hilft jemandem.

25
Matheus Rocha

Matt hat eine gute Antwort, aber es entfernt alle Argumente, die an das Skript übergeben wurden. Hier ist meine Modifikation, die Argumente enthält. Ich habe auch Stephens Fix für das Problem mit dem Arbeitsverzeichnis in Windows 8 integriert.

@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...
22
jxmallett

Ich verwende PowerShell, um das Skript mit erhöhten Rechten neu zu starten, wenn dies nicht der Fall ist. Fügen Sie diese Zeilen ganz oben in Ihr Skript ein.

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

Ich habe die 'net name'-Methode aus @ Matts Antwort kopiert. Seine Antwort ist viel besser dokumentiert und enthält Fehlermeldungen und Ähnliches. Dieser hat den Vorteil, dass PowerShell bereits unter Windows 7 und höher installiert und verfügbar ist. Keine temporären VBScript-Dateien (* .vbs), und Sie müssen keine Tools herunterladen.

Diese Methode sollte ohne Konfiguration oder Setup funktionieren, solange Ihre PowerShell-Ausführungsberechtigungen nicht gesperrt sind.

19
Ryan Bemrose

Für einige Programme, die das Supergeheimnis einstellen __COMPAT_LAYER Umgebungsvariable zu RunAsInvokerwird funktionieren . Überprüfen Sie dies:

set "__COMPAT_LAYER=RunAsInvoker"
start regedit.exe

Auf diese Weise wird der Benutzer jedoch nicht dazu aufgefordert, ohne Administratorrechte fortzufahren.

13
npocmaka

Ich habe dies am Anfang des Skripts eingefügt:

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

Obwohl dies nicht direkt auf diese Frage zutrifft, hat mich Google hierher gebracht, als ich meine .bat-Datei ausführen wollte, die über den Taskplaner erhöht wurde.

Der einfachste Ansatz war, eine Verknüpfung zur .bat-Datei zu erstellen, da Sie für eine Verknüpfung Run as administrator direkt aus den erweiterten Eigenschaften.

Wenn Sie die Verknüpfung über den Taskplaner ausführen, wird die .bat-Datei mit erhöhten Rechten ausgeführt.

0
Hugo Delsing