배치 파일을 높게 실행하고 싶습니다. 상승하지 않은 경우 사용자가 배치를 상승 된 상태로 다시 시작할 수있는 옵션을 제공하십시오.
시스템 변수를 설정하고 두 파일을 프로그램 파일 위치에 복사 한 다음 드라이버 설치 프로그램을 시작하기 위해 배치 파일을 작성하고 있습니다. Windows 7 / Windows Vista 사용자 ( UAC 사용 가능 및 로컬 관리자 인 경우에도)를 마우스 오른쪽 단추로 클릭하고 “관리자 권한으로 실행”을 선택하지 않고 실행하면 두 파일을 복사하고 시스템 변수를 쓰는 ‘액세스 거부’가 표시됩니다. .
사용자가 실제로 관리자 인 경우 명령을 사용하여 배치를 자동으로 다시 시작하려고합니다. 그렇지 않으면 관리자가 아닌 경우 배치 파일을 실행하려면 관리자 권한이 필요하다고 말하고 싶습니다. xcopy 를 사용 하여 파일을 복사하고 REG ADD 를 사용하여 시스템 변수를 작성합니다. 가능한 Windows XP 컴퓨터를 처리하기 위해 해당 명령을 사용하고 있습니다. 이 주제에서 비슷한 질문을 찾았지만 배치 파일을 다시 시작하는 데 도움이되는 것은 없습니다.
답변
당신은으로 스크립트 호출 자체를 가질 수 psexec에 의 -h
옵션이 상승 실행합니다.
액세스 권한 거부 오류가있는 경우에만 높은 권한으로 다시 시도 할 수 있습니까?
또는, 당신은 단순히위한 명령을 가질 수 xcopy
와 reg.exe
항상 실행할 수 psexec -h
있지만,이 입력에 암호 (스크립트에 암호를 포함하는 경우 또는 안전하지 않은)마다 필요로하는 경우는 최종 사용자에 대한 성가신 것 …
답변
외부 도구를 사용할 필요없이 쉬운 방법이 있습니다 -Windows 7, 8, 8.1 및 10에서 잘 실행되며 이전 버전과도 호환됩니다 (Windows XP에는 UAC가 없으므로 높이가 필요하지 않습니다). 스크립트가 진행됩니다).
이 코드를 확인하십시오 ( Windows 7 의 스레드 배치 파일- “액세스가 거부되었습니다”에 게시 된 NIronwolf의 코드에서 영감을 얻었습니다).하지만 코드를 개선했습니다. 관리자 권한 확인) :
::::::::::::::::::::::::::::::::::::::::::::
:: 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
이 스크립트는 NET FILE
관리자 권한 이 필요 하다는 사실을 활용 하고 errorlevel 1
없는 경우 반환 합니다. 권한 상승을 위해 배치 파일을 다시 시작하는 스크립트를 작성하면 권한이 상승됩니다. 이로 인해 Windows가 UAC 대화 상자를 표시하고 관리자 계정과 암호를 묻습니다.
Windows 7, 8, 8.1, 10 및 Windows XP에서 테스트했습니다. 모두 잘 작동합니다. 장점은 시작 지점 후에 디버깅 목적으로 Windows 서비스를 다시 설치하고 다시 실행하려는 경우 (예 : mypackage.msi가 서비스 설치 프로그램 패키지 인 경우) 시스템 관리자 권한이 필요한 항목을 배치 할 수 있다는 것입니다. :
msiexec /passive /x mypackage.msi
msiexec /passive /i mypackage.msi
net start myservice
이 권한 상승 스크립트가 없으면 UAC는 관리자와 암호를 세 번 묻습니다. 이제 처음에는 한 번만 요청하고 필요한 경우에만 요청합니다.
자동 상승 대신 관리자 권한이없는 경우 스크립트에 오류 메시지 만 표시하고 종료해야하는 경우 훨씬 간단합니다. 스크립트 시작 부분에 다음을 추가하면됩니다.
@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 ...
이런 식으로 사용자는 마우스 오른쪽 버튼을 클릭하고 “관리자 권한으로 실행”을 선택해야 합니다. 스크립트 REM
는 관리자 권한이 감지되면 명령문 다음에 진행 되고 그렇지 않으면 오류와 함께 종료됩니다. 이 필요하지 않은 경우 PAUSE
제거하십시오.
중요 : NET FILE [...] EXIT /D)
같은 줄에 있어야합니다. 가독성을 높이기 위해 여기에 여러 줄로 표시됩니다!
일부 컴퓨터에서는 위의 새 버전에서 이미 해결 된 문제가 발생했습니다. 하나는 다른 큰 따옴표 처리로 인한 것이고 다른 하나는 Windows 7 컴퓨터에서 UAC가 비활성화 (최저 수준으로 설정)되어 스크립트가 계속해서 자신을 호출하기 때문입니다.
경로에서 따옴표를 제거하고 나중에 다시 추가 하여이 문제를 해결했으며 스크립트가 높은 권한으로 다시 시작될 때 추가되는 추가 매개 변수를 추가했습니다.
큰 따옴표는 다음에 의해 제거됩니다 (자세한 내용은 여기 ) :
setlocal DisableDelayedExpansion
set "batchPath=%~0"
setlocal EnableDelayedExpansion
그런 다음을 사용하여 경로에 액세스 할 수 있습니다 !batchPath!
. 큰 따옴표가 포함되어 있지 않으므로 "!batchPath!"
나중에 스크립트에서 말하는 것이 안전합니다 .
라인
if '%1'=='ELEV' (shift & goto gotPrivileges)
VBScript 스크립트 가 스크립트를 이미 호출하여 권한을 높이고 있는지 확인하여 끝없는 재귀를 피합니다. 를 사용하여 매개 변수를 제거합니다 shift
.
최신 정보:
-
Windows 10 에서
.vbs
확장명 을 등록하지 않으려면 위의 스크립트에서 줄 을 바꿨습니다. 또한 스크립트 디렉토리를 기본값으로 설정하기 위해 Stephen (별도의 답변)과 Tomáš Zato (의견)에서 제안한대로 추가 되었습니다.
"%temp%\OEgetPrivileges.vbs"
"%SystemRoot%\System32\WScript.exe" "%temp%\OEgetPrivileges.vbs"
cd /d %~dp0
-
이제 스크립트는 명령 행 매개 변수를 전달합니다. 관찰과 영감을 주신 jxmallet, TanisDLJ 및 Peter Mortensen에게 감사합니다.
-
Artjom B.의 힌트에 따르면, 나는 그것을 분석 하고 매개 변수 의 파일 이름을 유지하는 로 대체
SHIFT
했습니다SHIFT /1
.%0
-
추가
del "%temp%\OEgetPrivileges_%batchName%.vbs"
받는 사람:gotPrivileges
(같은 부분은 정리하는 MLT가 제안).%batchName%
다른 배치를 병렬로 실행할 경우 영향을 피하기 위해 추가되었습니다 . 파일 이름 만 추출하는for
등의 고급 문자열 함수 를 이용하려면 사용해야 합니다%%~nk
. -
최적화 된 스크립트 구조, 개선 (
vbsGetPrivileges
파일의 경로 나 이름을 쉽게 변경할 수있는 모든 곳에서 참조되는 추가 된 변수 ,.vbs
배치를 늘려야 할 경우 에만 파일 삭제 ) -
경우에 따라 고도에 다른 호출 구문이 필요했습니다. 스크립트가 작동하지 않으면 다음 매개
set cmdInvoke=0
set winSysFolder=System32
변수를set cmdInvoke=1
확인하십시오 . 첫 번째 매개 변수를로 변경하고 이미 문제가 해결되었는지 확인하십시오.cmd.exe
고도를 수행하는 스크립트에 추가 됩니다.
또는 두 번째 매개 변수를로 변경하면winSysFolder=Sysnative
64 비트 시스템에서 도움이 될 수 있지만 대부분의 경우 필요하지는 않습니다. (ADBailey가이를보고했습니다). “Sysnative”는 32 비트 스크립트 호스트 (예 : Visual Studio 빌드 프로세스 또는 다른 32 비트 응용 프로그램에서 스크립트 호출)에서 64 비트 응용 프로그램을 시작하는 경우에만 필요합니다. -
매개 변수가 어떻게 해석되는지 더 명확하게하기 위해 다음과 같이 표시합니다
P1=value1 P2=value2 ... P9=value9
. 경로와 같은 매개 변수를 큰 따옴표로 묶어야하는 경우에 특히 유용합니다 (예 🙂"C:\Program Files"
. -
VBS 스크립트를 디버깅하려는 경우 여기에
//X
제안 된대로 첫 번째 매개 변수로 WScript.exe에 매개 변수를 추가 할 수 있습니다 (CScript.exe에 대해 설명되어 있지만 WScript.exe에서도 작동 함).
유용한 링크:
- 배치 파일에서 특수 문자의 의미 :
따옴표 ( “) , Bang (!) , Caret (^) , Ampersand (&) , 기타 특수 문자
답변
jcoder와 Matt이 언급했듯이 PowerShell은 쉽게 만들었으며 새 스크립트를 만들지 않고도 배치 스크립트에 포함시킬 수도 있습니다.
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
답변
Matt의 훌륭한 답변을 사용하고 있지만 고급 스크립트를 실행할 때 Windows 7과 Windows 8 시스템간에 차이가 있습니다.
Windows 8에서 스크립트가 승격되면 현재 디렉토리는로 설정됩니다 C:\Windows\system32
. 다행히도 현재 디렉토리를 현재 스크립트의 경로로 변경하면 쉬운 해결 방법이 있습니다.
cd /d %~dp0
참고 : cd /d
드라이브 문자도 변경했는지 확인하십시오.
이를 테스트하기 위해 다음을 스크립트에 복사 할 수 있습니다. 동일한 결과를 보려면 두 버전에서 정상적으로 실행하십시오. 관리자 권한으로 실행하여 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
답변
나는 이것을 이렇게한다 :
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
이 방법은 간단하며 Windows 기본 명령 만 사용합니다. 배치 파일을 재배포해야하는 경우 유용합니다.
CD /d %~dp0
현재 디렉토리를 파일의 현재 디렉토리로 설정합니다 ( /d
옵션으로 인해 파일이있는 드라이브에 관계없이 아직없는 경우 ).
%~nx0
확장자가있는 현재 파일 이름을 반환합니다 (확장자를 포함하지 않고 폴더에 이름이 같은 exe가 있으면 exe를 호출합니다).
이 게시물에는 답장이 너무 많아서 답을 볼 수 있을지도 모르겠습니다.
어쨌든 다른 답변에 제안 된 다른 솔루션 보다이 방법이 더 간단하다는 것을 알았습니다. 누군가에게 도움이되기를 바랍니다.
답변
Matt는 훌륭한 답변을 제공하지만 스크립트에 전달 된 모든 인수를 제거합니다. 인수를 유지하는 수정 사항은 다음과 같습니다. 또한 Windows 8의 작업 디렉토리 문제에 대한 Stephen의 수정 프로그램을 통합했습니다.
@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...
답변
PowerShell을 사용하여 높지 않은 스크립트를 다시 시작합니다. 이 줄을 스크립트 맨 위에 놓으십시오.
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
@Matt의 답변에서 ‘net name’메서드를 복사했습니다. 그의 대답은 훨씬 잘 문서화되어 있으며 오류 메시지 등이 있습니다. 이것은 Windows 7 이상에서 PowerShell이 이미 설치되어 있고 사용 가능하다는 이점이 있습니다. 임시 VBScript (*. vbs) 파일이 없으므로 도구를 다운로드 할 필요가 없습니다.
이 방법은 PowerShell 실행 권한이 잠겨 있지 않는 한 구성이나 설정없이 작동합니다.