มีวิธีที่ง่ายโดยไม่จำเป็นต้องใช้เครื่องมือภายนอก - มันทำงานได้ดีกับWindows 7, 8, 8.1 และ 10และสามารถใช้งานร่วมกับระบบย้อนหลังได้เช่นกัน (Windows XP ไม่มี UAC ใด ๆ ดังนั้นจึงไม่จำเป็นต้องเพิ่มระดับความสูง กรณีที่สคริปต์เพิ่งดำเนินการ)
ลองดูโค้ดนี้ (ฉันได้รับแรงบันดาลใจจากโค้ดของ NIronwolf ที่โพสต์ในไฟล์ Batch - "Access Denied" ใน Windows 7? ) แต่ฉันปรับปรุงมันแล้ว - ในเวอร์ชั่นของฉันไม่มีไดเรกทอรีใดที่สร้างและลบออกไป ตรวจสอบสิทธิ์ผู้ดูแลระบบ):
::::::::::::::::::::::::::::::::::::::::::::
:: 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)
จะต้องอยู่ในบรรทัดเดียวกัน มันแสดงที่นี่ในหลายบรรทัดเพื่อให้อ่านง่ายขึ้น!
ในบางเครื่องฉันพบปัญหาซึ่งแก้ไขได้ในเวอร์ชั่นใหม่ข้างต้นแล้ว หนึ่งเกิดจากการจัดการคำพูดสองครั้งที่แตกต่างกันและปัญหาอื่น ๆ เกิดจากข้อเท็จจริงที่ว่า UAC ถูกปิดใช้งาน (ตั้งค่าเป็นระดับต่ำสุด) บนเครื่อง Windows 7 ดังนั้นสคริปต์จึงเรียกตัวเองซ้ำแล้วซ้ำอีก
ฉันได้รับการแก้ไขในขณะนี้โดยการแยกเครื่องหมายคำพูดในเส้นทางและเพิ่มอีกครั้งในภายหลังและฉันได้เพิ่มพารามิเตอร์พิเศษซึ่งจะถูกเพิ่มเมื่อสคริปต์เปิดตัวอีกครั้งด้วยสิทธิ์ที่ยกระดับ
เครื่องหมายคำพูดคู่ถูกลบโดยต่อไปนี้ (รายละเอียดอยู่ที่นี่ ):
setlocal DisableDelayedExpansion
set "batchPath=%~0"
setlocal EnableDelayedExpansion
!batchPath!
จากนั้นคุณสามารถเข้าถึงเส้นทางโดยใช้ ไม่มีเครื่องหมายอัญประกาศคู่ใด ๆ ดังนั้นจึงปลอดภัยที่จะพูด"!batchPath!"
ในภายหลังในสคริปต์
เส้น
if '%1'=='ELEV' (shift & goto gotPrivileges)
ตรวจสอบว่าสคริปต์ได้รับการเรียกใช้โดยสคริปต์VBScriptเพื่อยกระดับสิทธิ์หรือไม่จึงหลีกเลี่ยงการเรียกซ้ำอีกครั้ง shift
มันเอาพารามิเตอร์ใช้
ปรับปรุง:
เพื่อหลีกเลี่ยงการลงทะเบียน.vbs
ส่วนขยายในวินโดวส์ 10ผมได้เปลี่ยนสาย
"%temp%\OEgetPrivileges.vbs"
โดย
"%SystemRoot%\System32\WScript.exe" "%temp%\OEgetPrivileges.vbs"
ในสคริปต์ข้างต้น เพิ่มcd /d %~dp0
ตามที่แนะนำโดย Stephen (คำตอบแยกต่างหาก) และโดยTomáš Zato (ความคิดเห็น) เพื่อตั้งค่าไดเรกทอรีสคริปต์เป็นค่าเริ่มต้น
ตอนนี้สคริปต์จะใช้พารามิเตอร์บรรทัดคำสั่งเพื่อให้เกียรติ ขอบคุณ 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
เปลี่ยนพารามิเตอร์ที่ 1 เป็นset cmdInvoke=1
และตรวจสอบว่าได้แก้ไขปัญหาแล้ว มันจะเพิ่มcmd.exe
ไปยังสคริปต์ที่ดำเนินการระดับความสูง
หรือพยายามเปลี่ยนพารามิเตอร์ตัวที่ 2 winSysFolder=Sysnative
ซึ่งอาจช่วยได้ (แต่โดยส่วนใหญ่แล้วไม่จำเป็นต้องใช้) ในระบบ 64 บิต (ADBailey ได้รายงานสิ่งนี้) "Sysnative" ใช้สำหรับเรียกใช้แอปพลิเคชัน 64 บิตจากโฮสต์สคริปต์ 32 บิต (เช่นกระบวนการสร้าง Visual Studio หรือการเรียกใช้สคริปต์จากแอปพลิเคชัน 32 บิตอื่น)
P1=value1 P2=value2 ... P9=value9
ที่จะทำให้มันชัดเจนมากขึ้นว่าค่าพารามิเตอร์จะถูกตีความผมแสดงได้ในขณะนี้เช่น "C:\Program Files"
นี้จะเป็นประโยชน์โดยเฉพาะอย่างยิ่งถ้าคุณจำเป็นต้องแนบพารามิเตอร์เช่นเส้นทางในราคาคู่เช่น
ถ้าคุณต้องการดีบักสคริปต์ VBS คุณสามารถเพิ่ม//X
พารามิเตอร์ลงใน WScript.exe เป็นพารามิเตอร์แรกตามที่แนะนำไว้ที่นี่ (อธิบายไว้สำหรับ CScript.exe แต่ใช้ได้กับ WScript.exe ด้วย)
ลิงค์ที่มีประโยชน์: