Jak mogę automatycznie podwyższyć plik wsadowy, aby w razie potrzeby żądał uprawnień administratora UAC?


209

Chcę, aby mój plik wsadowy był uruchamiany tylko z podwyższonym poziomem uprawnień. Jeśli nie jest podniesiony, podaj opcję ponownego uruchomienia partii jako podniesiony.

Piszę plik wsadowy, aby ustawić zmienną systemową, skopiować dwa pliki do lokalizacji Program Files i uruchomić instalator sterownika. Jeśli użytkownik systemu Windows 7 / Windows Vista ( włączony UAC i nawet jeśli jest lokalnym administratorem) uruchomi go bez kliknięcia prawym przyciskiem myszy i wybrania opcji „Uruchom jako administrator”, otrzyma polecenie „Odmowa dostępu” kopiujące dwa pliki i zapisujące zmienną systemową .

Chciałbym użyć polecenia, aby automatycznie ponownie uruchomić pakiet z podwyższonym poziomem uprawnień, jeśli użytkownik jest w rzeczywistości administratorem. W przeciwnym razie, jeśli nie są administratorem, chcę im powiedzieć, że potrzebują uprawnień administratora, aby uruchomić plik wsadowy. Używam xcopy do kopiowania plików i REG ADD do zapisywania zmiennej systemowej. Używam tych poleceń, aby radzić sobie z możliwymi komputerami z Windows XP. Znalazłem podobne pytania na ten temat, ale nic nie dotyczy ponownego uruchomienia pliku wsadowego jako podniesionego.


2
Sprawdź, co napisałem - nie potrzebujesz zewnętrznego narzędzia, skrypt automatycznie sprawdza uprawnienia administratora i automatycznie podnosi się w razie potrzeby.
Matt

1
Zastanów się, czy odpowiedź Matta byłaby zaznaczona? Tak mi się wydaje.
akauppi,


Zapoznaj się z nowymi wskazówkami dla systemu Windows 10 w sekcji komentarzy opublikowanego skryptu wsadowego .
Matt

4
Z cmd: @powershell Start-Process cmd -Verb runas. Z Powershell po prostu upuść @powershell. To zaczyna cmd z podwyższonymi prawami.
BrunoLM,

Odpowiedzi:


20

Możesz mieć wywołanie skryptu z opcją psexec , -haby uruchomić na podwyższonym poziomie.

Nie jestem pewien, jak byś wykrył, czy już działa z podwyższonym poziomem uprawnień, czy nie ... może spróbuj ponownie z podwyższonym poziomem perms tylko wtedy, gdy występuje błąd odmowy dostępu?

Lub możesz po prostu mieć komendy xcopyi reg.exezawsze je uruchamiać psexec -h, ale dla użytkownika końcowego byłoby denerwujące, gdyby za każdym razem musieli wprowadzać swoje hasło (lub niepewne, jeśli podałeś hasło w skrypcie) ...


10
Dzięki za odpowiedzi. Niestety nie sądzę, żebym mógł używać czegokolwiek poza standardowymi narzędziami systemu Windows Vista / 7, ponieważ będą one dostępne dla klientów spoza mojego biura. Nie sądzę, że mogę legalnie rozpowszechniać PSExec.
PDixon724,

2
Tak, myślę, że masz rację - chociaż PSExec jest teraz narzędziem Microsoft (ponieważ wykupili facetów z Sysinternals!), EULA zabrania dystrybucji :(
ewall

2
Myślę, że moje opcje są dość ograniczone. Gdybym wiedział, jak napisać kod w VB, mógłbym uczynić go exe z manifestem administratora, ale nie wiedziałbym nawet, od czego zacząć. Chyba po prostu ostrzeżę na początku partii, aby działała jako administrator, jeśli korzystają z systemu Windows Vista / 7. Dziękuje wszystkim.
PDixon724,

1
Innym narzędziem innej firmy, które może być swobodnie rozpowszechniane i łatwe do zintegrowania i nauki, jest AutoIt ; ta strona pokazuje, w jaki sposób skrypt żąda podniesienia uprawnień.
ewall

4
psexec -hnie działa: „Nie można zainstalować usługi PSEXESVC: Odmowa dostępu.”. Musisz mieć już uprawnienia administratora, aby uruchomić psexec.
Nicolas

319

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 FILEwymaga 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 REMinstrukcji, 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 .vbsrozszerzenie 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 %~dp0jak 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 SHIFTnim SHIFT /1, co zachowuje nazwę pliku dla %0parametru

  • Dodano del "%temp%\OEgetPrivileges_%batchName%.vbs"do :gotPrivilegessekcji, 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ć, foraby 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 vbsGetPrivilegesktórej teraz można się odwoływać wszędzie, umożliwiająca łatwą zmianę ścieżki lub nazwy pliku, usuwanie .vbspliku 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=1i sprawdź, czy to już rozwiązuje problem. Dodanie cmd.exedo 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ć //Xparametr 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:


9
Świetna odpowiedź, choć nieco mnie to dziwi, że musisz zrobić wszystko, aby zrobić coś, co w niektórych przypadkach jest wyraźnie konieczne.
jcoder

50
Rzeczywiście, w języku wsadowym Windows wyraźnie brakuje polecenia ELEVATE.
Matt

2
Być może łatwiej jest z PowerShellem, który wydaje się być zatwierdzonym językiem skryptowym dla bardziej skomplikowanych rzeczy, ale jak dotąd nie zadałem sobie trudu, aby się go nauczyć :(
jcoder

1
Składnia w PowerShell jest zupełnie inna (składnia czasownik-rzeczownik), ale umożliwia łatwe wywoływanie zestawów .NET. Ale trudniej jest sobie z tym poradzić (podpisywanie skryptów itp.).
Matt

2
@Matt Czy możesz sprawdzić, czy za tą odrzuconą edycją w Twojej odpowiedzi kryje się jakaś prawda ?
Artjom B.,

41

Jak wspomnieli jcoder i Matt, PowerShell ułatwił to, a nawet można go było osadzić w skrypcie wsadowym bez tworzenia nowego skryptu.

Zmodyfikowałem skrypt Matta:

:: 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
Masz rację, jeśli PowerShell jest zainstalowany, możesz go użyć do uruchomienia pliku wsadowego z elewacją (dziękuję za fragment kodu!). I tak, etykieta nie jest potrzebna. Dziękuję za podpowiedzi, warto dać +1 ... :-)
Matt

2
Po wywołaniu z cmd Powershell.exe nie ma opcji -verb runas. Istnieje, jeśli jesteś już w PowerShell.
Adil Hindistan

1
Naprawdę podoba mi się to rozwiązanie, działa świetnie dla mnie. W systemie Windows 8.1 do działania potrzebowałem etykiety: gotPrivileges.
ShaunO

Uderzam w problem, jeśli ten plik wsadowy jest zdalny na ścieżce UNC.
Ryan Beesley,

Dodałem katalog zmian na starcie, uprościłem przepływ i trochę wyczyściłem. WorkingDirectoryStart-Processrunas
Katalogu

28

Korzystam z doskonałej odpowiedzi Matta, ale widzę różnicę między moimi systemami Windows 7 i Windows 8 podczas uruchamiania podwyższonych skryptów.

Po podniesieniu skryptu w systemie Windows 8 bieżący katalog jest ustawiony na C:\Windows\system32. Na szczęście można łatwo obejść ten problem, zmieniając bieżący katalog na ścieżkę bieżącego skryptu:

cd /d %~dp0

Uwaga: Użyj, cd /daby upewnić się, że litera dysku również została zmieniona.

Aby to przetestować, możesz skopiować następujące skrypty. Uruchom normalnie w dowolnej wersji, aby zobaczyć ten sam wynik. Uruchom jako administrator i zobacz różnicę w systemie 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
Dobra wskazówka, Stephen. Skrypt powinien więc zakończyć się, cd %~dp0aby zachować swoją bieżącą ścieżkę (zakładam, że działa to również w Win7, więc można użyć tego samego polecenia, chociaż jest ono potrzebne tylko w Win8 +). +1 za to!
Matt

2
Warto zauważyć, że było to również wymagane w moim systemie z Windows 7.
Meh-uk

1
lub użyj pushd %~dp0zamiast ... dlaczego? ponieważpopd
Jaroslav Záruba

27

Robię to w ten sposób:

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

W ten sposób jest to proste i używaj tylko domyślnych poleceń systemu Windows. Świetnie, jeśli musisz ponownie rozpowszechnić plik wsadowy.

CD /d %~dp0Ustawia bieżący katalog na bieżący katalog pliku (jeśli nie jest, niezależnie od dysku, w którym znajduje się plik, dzięki /dopcji).

%~nx0 Zwraca bieżącą nazwę pliku z rozszerzeniem (jeśli nie dodasz rozszerzenia i w folderze znajduje się plik exe o tej samej nazwie, wywoła plik exe).

W tym poście jest tyle odpowiedzi, że nawet nie wiem, czy moja odpowiedź zostanie wyświetlona.

W każdym razie uważam, że ten sposób jest prostszy niż inne rozwiązania zaproponowane w innych odpowiedziach, mam nadzieję, że to komuś pomoże.


4
cd% ~ dp0 nie będzie działać na dyskach sieciowych, zamiast tego użyj pushd% ~ dp0.
Stavm,

1
Uwielbiam prostotę tej odpowiedzi. I wreszcie powód do korzystania z Jscript!
Joe Coder,

1
Magia! Dziękuję Ci bardzo.
Daniele Orlando,

1
@Wolf Wpisałem ogromną odpowiedź tylko po to, by zrozumieć, że źle cię zrozumiałem ... Rozumiem teraz. Zmienię to, aby uwzględnić /d. Dziękuję kolego :) (PS: Pianista też tutaj!)
Matheus Rocha

1
Działa to świetnie, ale może być dobrym pomysłem przeniesienie cdpolecenia na początek (zapewnia to, że ścieżka jest również dostępna dla skryptu z podwyższonym poziomem uprawnień - w przeciwnym razie skrypt z podwyższonym poziomem uprawnień uruchamia się po prostu z systemu32). Powinieneś także przekierować polecenie net do nul, aby ukryć jego dane wyjściowe:net session >nul 2>&1
Nulano

23

Matt ma świetną odpowiedź, ale usuwa wszelkie argumenty przekazane do skryptu. Oto moja modyfikacja, która przechowuje argumenty. Włączyłem również poprawkę Stephena dotyczącą problemu z katalogiem roboczym w systemie 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
To przydatna odpowiedź. Jednak ECHO UAC.ShellExecute....zgodnie z kolejnością "batchArgs!"nie rozwija zmiennej. Zastosowanie "!batchArgs!". Moja edycja została odrzucona, więc komentuję.
cebula mielona

1
@fliedonion dobrze zauważony! Nie jestem pewien, dlaczego twoja edycja została odrzucona, ponieważ zdecydowanie była to literówka, a Twoja poprawka działa. Dokonałem zmiany sam i przetestowałem ją na Win 8.1. Teraz znajdę wszystkie skrypty, w których używam tego kodu ....
jxmallett,

2
Skrypt się zepsuł podczas używania argumentów cytowanych, takich jak test.bat "a thing"lub "test script.bat" arg1 arg2. Wszystko naprawione teraz.
jxmallett,

Udało mi się go zepsuć (z mojej winy: uruchomienie skryptu z zamapowanego dysku sieciowego, ponieważ administrator i zwykły użytkownik nie mają tego samego odwzorowania). Nadal: czy istnieje sposób, aby zobaczyć wynik? Dla mnie musiałem znaleźć plik .vbs i zmienić / c na a / K, a następnie zobaczyłem go ręcznie.
Andreas Reiff

21

Korzystam z programu PowerShell, aby ponownie uruchomić skrypt z podwyższonym poziomem uprawnień, jeśli nie jest. Umieść te linie na samym początku skryptu.

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

Skopiowałem metodę „net name” z odpowiedzi @ Matta. Jego odpowiedź jest znacznie lepiej udokumentowana i zawiera komunikaty o błędach itp. Ta ma tę zaletę, że PowerShell jest już zainstalowany i dostępny w systemie Windows 7 i nowszych. Brak tymczasowych plików VBScript (* .vbs) i nie trzeba pobierać narzędzi.

Ta metoda powinna działać bez jakiejkolwiek konfiguracji lub konfiguracji, o ile uprawnienia do wykonywania programu PowerShell nie są zablokowane.


dostarczając listę oddzielonych spacjami argumentów otoczonych cudzysłowami, aby traktować ją jako jedną, /c %~fnx0 %*'część wydaje się pozostawiać każdą część oprócz pierwszej. Np. test.bat "arg1 arg2 arg3"Tylko arg1 jest przekazywany do przodu
Nicolas Mommaerts

Wydaje się, że bez względu na to, Start-Process usuwa wszystkie podwójne cudzysłowy z listy argumentów.
Nicolas Mommaerts 10.10.14

Pracuje dla mnie! Używam tego do netsh int set int %wifiname% Enable/Disable.
Marslo,

2
Miałem ten sam problem, co powyżej Nicolas Mommaerts. Nie rozumiem, dlaczego to działa (najlepszy rodzaj poprawki), ale następujące działają tak, jak powinny (zwróć uwagę na wszystkie dodatkowe znaki cudzysłowu na końcu): net file 1>nul 2>nul && goto :run || powershell -ex unrestricted -Command "Start-Process -Verb RunAs -FilePath '%comspec%' -ArgumentList '/c ""%~fnx0""""'"
trzęsie

Innym problemem (niedogodnością) jest to, że skrypt wstrzymuje się (czeka na dane wejściowe użytkownika), jeśli usługa serwera nie działa (wyłączam ją z przyczyn). Zwykle testuję uprawnienia administratora, próbując zapisać w lokalizacji pliku HOSTS , ale być może lepiej jest wywołać komendę PowerShell -Verb runas , zamiast polegać na włączonych usługach Windows lub próbować zapisywać pliki.
script'n'code

15

W przypadku niektórych programów ustawianie super tajnej __COMPAT_LAYERzmiennej środowiskowej na RunAsInvoker działanie. Sprawdź to:

set "__COMPAT_LAYER=RunAsInvoker"
start regedit.exe

Chociaż w ten sposób nie pojawi się monit UAC, użytkownik będzie kontynuował bez uprawnień administratora.


1
Link do strony Microsoft już nie działał, więc zmieniłem go na treść na archive.org. Jeśli ktoś może znaleźć działający link do treści w witrynie Microsoft, ale wszystkie środki należy zaktualizować do tego.
RockPaperLizard

1
nadal jest w średniej integralności nie podniesiony , więc nie możesz edytować HKLM w regedit. Po prostu ominął uac.
HackingAddict1337

5

Wkleiłem to na początku skryptu:

:: 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
Lubię przetwarzanie arg w twoim skrypcie. Należy jednak pamiętać, że caclsjest przestarzałe w systemie Windows 7 i nowszych wersjach systemu Windows.
Matt

Fsutil Brud jest jeszcze lepszy
Wolf

1
Czy wiesz, że wiersz pushd "%CD%"zapisuje bieżący katalog roboczy i przechodzi do bieżącego katalogu roboczego?
Wolf

3

Pisałem gsudo, dla okien : który jest wysunięty w bieżącej konsoli (bez przełączania kontekstu w nowym oknie), z pamięci podręcznej poświadczeń (zmniejszony wyskakujące okienka UAC), a także podnosi poleceń PowerShell .sudo

Pozwala na podniesienie poleceń wymagających uprawnień administratora lub całej partii, jeśli chcesz. Po prostu przygotuj się gsudo przed wszystkim, co musi być podniesione.

Przykładowy plik wsadowy, który podnosi się za pomocą gsudo:

EDYCJA: Nowa wersja jednoliniowa, która działa z dowolnym językiem Windows i pozwala uniknąć problemów z Whoami :

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

Alternatywa (wersja oryginalna):

@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

Zainstalować:

Zobacz gsudo w akcji: demo gsudo


Chłodny. Dzięki. W jakich wersjach systemu Windows działa?
RockPaperLizard

Pakiet testowy działa na serwerze 2019, a moim lokalnym urządzeniem deweloperskim jest system Windows 10 1909. Niestety nie przetestowałem zgodności z innym starszym systemem operacyjnym.
Gerardo Grignoli

Dziękuję Gerardo. Jeśli ktoś spróbuje tego w innych wersjach systemu Windows, opublikuj swoje wyniki.
RockPaperLizard

Właśnie przetestowałem gsudo v0.7 na Windows 8.1 i działałem. Instalacja nie jest trywialna .Net Framework 4.6. Na szczęście choco install dotnet4.6.2przyniosło trudne do zdobycia zależności. Następnie gsudo config Prompt "$p# "naprawiono problem z ConHostwyświetlaniem niewłaściwego monitu (znaki sekwencji ucieczki zamiast czerwonego ostrza). @RockPaperLizard
Gerardo Grignoli

Dziękuję bardzo Gerardo. Czy można go przekompilować do pracy z dowolnymi wersjami .Net Framework wcześniejszymi niż 4.6, czy też zależy to od niektórych funkcji specyficznych dla 4.6?
RockPaperLizard

2

Chociaż nie dotyczy bezpośrednio tego pytania, ponieważ potrzebuje pewnych informacji dla użytkownika, Google przyniósł mnie tutaj, gdy chciałem uruchomić mój plik .bat z poziomu harmonogramu zadań.

Najprostszym podejściem było utworzenie skrótu do pliku .bat, ponieważ dla skrótu można ustawić Run as administrator bezpośrednio z właściwości zaawansowanych.

Uruchomienie skrótu z harmonogramu zadań powoduje podniesienie pliku .bat.


0

Korzystanie z PowerShell.

Jeśli plik cmd jest długi, używam pierwszego, aby wymagać podniesienia, a następnie wywołuję ten, który wykonuje właściwą pracę.

Jeśli skrypt jest prostym poleceniem, wszystko może zmieścić się w jednym pliku cmd. Nie zapomnij podać ścieżki do plików skryptów.

Szablon:

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

Przykład 1:

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

Przykład 2:

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

0

Spróbuj tego:

@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

Jeśli potrzebujesz informacji o tym pliku wsadowym, uruchom fragment kodu 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

Poniższe rozwiązanie jest czyste i działa idealnie.

  1. Pobierz plik zip Elevate ze strony https://www.winability.com/download/Elevate.zip

  2. Wewnątrz zip powinny znajdować się dwa pliki: Elevate.exe i Elevate64.exe. (Ta ostatnia jest natywną kompilacją 64-bitową, jeśli jej potrzebujesz, chociaż zwykła wersja 32-bitowa, Elevate.exe powinna działać poprawnie zarówno w 32-bitowej, jak i 64-bitowej wersji systemu Windows)

  3. Skopiuj plik Elevate.exe do folderu, w którym system Windows zawsze może go znaleźć (na przykład C: / Windows). Lub lepiej możesz skopiować w tym samym folderze, w którym planujesz przechowywać plik nietoperza.

  4. Aby użyć go w pliku wsadowym, po prostu wstaw polecenie, które chcesz wykonać jako administrator, za pomocą polecenia Elevate:

 elevate net start service ...

2
To polecenie otwiera tylko okno dialogowe, w którym pyta użytkownika, czy to polecenie może zostać wykonane. Nie można więc użyć tego polecenia w pliku wsadowym, co powinno działać BEZ interakcji użytkownika.
Radon8472,

Gdyby można było podnieść BEZ interakcji użytkownika, byłaby to ogromna dziura w zabezpieczeniach, prawda? Każdy wirus zacząłby korzystać z tej metody w celu podniesienia się bez zgody użytkownika.
Andrei Belogortseff
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.