Istnieje prosty sposób bez potrzeby korzystania z zewnętrznego narzędzia - działa dobrze z Windows 7, 8, 8.1 i 10 i jest również kompatybilny wstecz (Windows XP nie ma UAC, więc podniesienie nie jest potrzebne - w tym jeśli skrypt po prostu działa).
Sprawdź ten kod (zainspirował mnie kod NIronwolf opublikowany w wątku Plik wsadowy - „Odmowa dostępu” w systemie Windows 7? ), Ale go poprawiłem - w mojej wersji nie ma żadnego katalogu utworzonego i usuniętego do sprawdź uprawnienia administratora):
::::::::::::::::::::::::::::::::::::::::::::
:: 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
Skrypt wykorzystuje fakt, że NET FILE
wymaga uprawnień administratora i zwracaerrorlevel 1
jeśli go nie masz. Podniesienie uprawnień odbywa się poprzez utworzenie skryptu, który ponownie uruchamia plik wsadowy w celu uzyskania uprawnień. Powoduje to, że system Windows wyświetla okno dialogowe UAC i prosi o podanie konta administratora i hasła.
Przetestowałem to z Windows 7, 8, 8.1, 10 i Windows XP - działa dobrze dla wszystkich. Zaletą jest to, że po punkcie początkowym możesz umieścić wszystko, co wymaga uprawnień administratora systemu, na przykład, jeśli zamierzasz ponownie zainstalować i ponownie uruchomić usługę Windows w celu debugowania (zakładając, że mypackage.msi jest pakietem instalatora usług) :
msiexec /passive /x mypackage.msi
msiexec /passive /i mypackage.msi
net start myservice
Bez tego skryptu podnoszącego uprawnienia UAC trzykrotnie prosi o podanie administratora i hasła - teraz na początku jest tylko raz i tylko w razie potrzeby.
Jeśli skrypt wymaga tylko wyświetlenia komunikatu o błędzie i wyjścia, jeśli nie ma żadnych uprawnień administratora zamiast automatycznego podnoszenia, jest to jeszcze prostsze: Możesz to osiągnąć, dodając następujące elementy na początku skryptu:
@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 ...
W ten sposób użytkownik musi kliknąć prawym przyciskiem myszy i wybrać „Uruchom jako administrator” . Skrypt będzie działał po REM
instrukcji, jeśli wykryje prawa administratora, w przeciwnym razie wyjdzie z błędem. Jeśli nie potrzebujesz PAUSE
, po prostu usuń go.
Ważne: NET FILE [...] EXIT /D)
musi znajdować się w tej samej linii. Jest wyświetlany tutaj w wielu wierszach dla lepszej czytelności!
Na niektórych maszynach napotkałem problemy, które zostały już rozwiązane w nowej wersji powyżej. Jeden z nich był spowodowany inną obsługą podwójnego cytowania, a drugi był związany z faktem, że UAC został wyłączony (ustawiony na najniższy poziom) na komputerze z systemem Windows 7, stąd skrypt ciągle się wywołuje.
Naprawiłem to teraz, usuwając cytaty ze ścieżki i dodając je później, i dodałem dodatkowy parametr, który jest dodawany, gdy skrypt uruchamia się ponownie z podwyższonymi uprawnieniami.
Podwójne cudzysłowy są usuwane przez (szczegóły są tutaj ):
setlocal DisableDelayedExpansion
set "batchPath=%~0"
setlocal EnableDelayedExpansion
Następnie możesz uzyskać dostęp do ścieżki za pomocą !batchPath!
. Nie zawiera podwójnych cudzysłowów, więc można bezpiecznie powiedzieć "!batchPath!"
później w skrypcie.
Linia
if '%1'=='ELEV' (shift & goto gotPrivileges)
sprawdza, czy skrypt został już wywołany przez skrypt VBScript w celu podniesienia uprawnień, dzięki czemu unika się niekończących się rekurencji. Usuwa parametr za pomocą shift
.
Aktualizacja:
Aby uniknąć konieczności zarejestrowania .vbs
rozszerzenie w systemie Windows 10 , I zastąpiły linię
"%temp%\OEgetPrivileges.vbs"
przez
"%SystemRoot%\System32\WScript.exe" "%temp%\OEgetPrivileges.vbs"
w skrypcie powyżej; również dodane, cd /d %~dp0
jak sugerują Stephen (osobna odpowiedź) i Tomáš Zato (komentarz), aby ustawić domyślny katalog skryptów.
Teraz skrypt honoruje przekazane mu parametry wiersza poleceń. Dzięki jxmallet, TanisDLJ i Peterowi Mortensenowi za spostrzeżenia i inspiracje.
Zgodnie ze wskazówkami Artjoma B. przeanalizowałem go i zastąpiłem SHIFT
nim SHIFT /1
, co zachowuje nazwę pliku dla %0
parametru
Dodano del "%temp%\OEgetPrivileges_%batchName%.vbs"
do :gotPrivileges
sekcji, aby wyczyścić (jak sugeruje mlt ). Dodano, %batchName%
aby uniknąć wpływu, jeśli uruchomisz różne partie równolegle. Pamiętaj, że musisz go użyć, for
aby móc korzystać z zaawansowanych funkcji łańcuchowych, takich jak %%~nk
, które wyodrębniają tylko nazwę pliku.
Zoptymalizowana struktura skryptu, ulepszenia (dodana zmienna, do vbsGetPrivileges
której teraz można się odwoływać wszędzie, umożliwiająca łatwą zmianę ścieżki lub nazwy pliku, usuwanie .vbs
pliku tylko w przypadku konieczności podniesienia partii)
W niektórych przypadkach do podniesienia wymagana była inna składnia wywołania. Jeśli skrypt nie działa, sprawdź następujące parametry:
set cmdInvoke=0
set winSysFolder=System32
Zmień pierwszy parametr na set cmdInvoke=1
i sprawdź, czy to już rozwiązuje problem. Dodanie cmd.exe
do skryptu wykonującego elewację.
Lub spróbuj zmienić drugi parametr na winSysFolder=Sysnative
, może to pomóc (ale w większości przypadków nie jest wymagane) w systemach 64-bitowych. (ADBailey to zgłosił). „Sysnative” jest wymagany tylko do uruchamiania 64-bitowych aplikacji z 32-bitowego hosta skryptów (np. Proces kompilacji Visual Studio lub wywołanie skryptu z innej aplikacji 32-bitowej).
Aby wyjaśnić, w jaki sposób interpretowane są parametry, wyświetlam to teraz P1=value1 P2=value2 ... P9=value9
. Jest to szczególnie przydatne, jeśli chcesz zawrzeć parametry takie jak ścieżki w podwójnych cudzysłowach, np "C:\Program Files"
.
Jeśli chcesz debugować skrypt VBS, możesz dodać //X
parametr do WScript.exe jako pierwszy parametr, zgodnie z sugestią tutaj (jest on opisany dla CScript.exe, ale działa również dla WScript.exe).
Przydatne linki: