ฉันจะยกระดับไฟล์แบตช์ของฉันโดยอัตโนมัติได้อย่างไรเพื่อให้มันร้องขอจากสิทธิ์ผู้ดูแลระบบ UAC หากจำเป็น


209

ฉันต้องการให้ไฟล์แบตช์ของฉันทำงานด้วยการยกระดับเท่านั้น หากไม่ได้รับการยกระดับให้ระบุตัวเลือกสำหรับผู้ใช้เพื่อเปิดแบตช์ใหม่ตามที่ยกระดับ

ฉันกำลังเขียนไฟล์แบตช์เพื่อตั้งค่าตัวแปรระบบคัดลอกสองไฟล์ไปยังตำแหน่งProgram Filesและเริ่มโปรแกรมติดตั้งไดรเวอร์ หากผู้ใช้ Windows 7 / Windows Vista ( เปิดใช้งานUACและแม้ว่าพวกเขาจะเป็นผู้ดูแลระบบในพื้นที่) ให้รันโดยไม่ต้องคลิกขวาและเลือก "Run as Administrator" พวกเขาจะได้รับ 'Access Denied' คัดลอกสองไฟล์และเขียนตัวแปรระบบ .

ฉันต้องการใช้คำสั่งเพื่อรีสตาร์ตแบตช์โดยอัตโนมัติหากผู้ใช้เป็นผู้ดูแลระบบ มิฉะนั้นหากพวกเขาไม่ใช่ผู้ดูแลฉันต้องการบอกพวกเขาว่าพวกเขาต้องการสิทธิ์ผู้ดูแลระบบเพื่อเรียกใช้ไฟล์แบตช์ ฉันใช้xcopyเพื่อคัดลอกไฟล์และREG ADDเพื่อเขียนตัวแปรระบบ ฉันใช้คำสั่งเหล่านั้นเพื่อจัดการกับเครื่อง Windows XP ที่เป็นไปได้ ฉันพบคำถามที่คล้ายกันในหัวข้อนี้ แต่ไม่มีอะไรเกี่ยวข้องกับการเปิดใช้งานไฟล์แบตช์อีกครั้ง


2
ตรวจสอบสิ่งที่ฉันโพสต์ - คุณไม่จำเป็นต้องใช้เครื่องมือภายนอกสคริปต์จะตรวจสอบสิทธิ์ของผู้ดูแลระบบและยกระดับตัวเองโดยอัตโนมัติหากจำเป็น
แมตต์

1
โปรดพิจารณาว่าคำตอบของแมตต์จะเป็นคำตอบที่ถูกหรือไม่? ดูเหมือนว่าฉัน
akauppi


โปรดพิจารณาคำแนะนำของWindows 10ใหม่ในส่วนความคิดเห็นของชุดสคริปต์ที่ฉันได้โพสต์
แมตต์

4
จาก @powershell Start-Process cmd -Verb runascmd: จาก PowerShell @powershellเพียงลดลง สิ่งนี้เริ่ม cmd ด้วยสิทธิ์ที่ยกระดับ
BrunoLM

คำตอบ:


20

คุณสามารถเรียกใช้สคริปต์ด้วยตัวเลือกของpsexec-hเพื่อเรียกใช้การยกระดับ

ฉันไม่แน่ใจว่าคุณจะตรวจพบได้อย่างไรว่ามีการทำงานในระดับที่สูงขึ้นหรือไม่ ... อาจลองใหม่ด้วย perms ที่ได้รับการอัปเดตเฉพาะในกรณีที่มีข้อผิดพลาดการเข้าถึงถูกปฏิเสธ

หรือคุณเพียงแค่มีคำสั่งสำหรับxcopyและreg.exeมักจะทำงานด้วยpsexec -hแต่มันจะน่ารำคาญสำหรับผู้ใช้ปลายทางหากพวกเขาจำเป็นต้องใส่รหัสผ่านในแต่ละครั้ง (หรือไม่ปลอดภัยหากคุณใส่รหัสผ่านในสคริปต์) ...


10
ขอบคุณสำหรับคำตอบ น่าเสียดายที่ฉันไม่คิดว่าฉันจะสามารถใช้สิ่งใดนอกเหนือจากเครื่องมือ Windows Vista / 7 ที่มีอยู่ในสต็อกได้เพราะจะเป็นการออกไปหาลูกค้านอกสำนักงานของฉัน ฉันไม่คิดว่าฉันสามารถแจกจ่าย PSExec ได้อย่างถูกกฎหมาย
PDixon724

2
ใช่ฉันคิดว่าคุณพูดถูก - แม้ว่าตอนนี้ PSExec เป็นเครื่องมือของ Microsoft (เนื่องจากพวกเขาซื้อ Sysinternals ออกมา!) EULA ห้ามการแจกจ่าย :(
ewall

2
ฉันคิดว่าตัวเลือกของฉันค่อนข้าง จำกัด ถ้าฉันรู้วิธีการเขียนโค้ดใน VB ฉันสามารถทำให้ exe เป็นรายการผู้ดูแลระบบ แต่ฉันก็ไม่รู้ด้วยซ้ำว่าจะเริ่มจากตรงไหน ฉันเดาว่าฉันจะเตือนที่จุดเริ่มต้นของชุดการเรียกใช้ในฐานะผู้ดูแลถ้าพวกเขากำลังเรียกใช้ Windows Vista / 7 ขอบคุณทุกคน
PDixon724

1
เครื่องมือของบุคคลที่ 3 อีกที่อาจจะได้อย่างอิสระสามารถเผยแพร่และง่ายต่อการเรียนรู้บูรณาการและเป็นAutoIt ; หน้านี้อธิบายวิธีที่สคริปต์ร้องขอสิทธิ์ยกระดับ
eWall

4
psexec -hไม่ทำงาน: 'ไม่สามารถติดตั้งบริการ PSEXESVC: การเข้าถึงถูกปฏิเสธ' คุณต้องมีสิทธิ์ของผู้ดูแลระบบเพื่อที่จะเรียกใช้ psexec
Nicolas

319

มีวิธีที่ง่ายโดยไม่จำเป็นต้องใช้เครื่องมือภายนอก - มันทำงานได้ดีกับ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 ด้วย)

ลิงค์ที่มีประโยชน์:


9
คำตอบที่ดีแม้ว่ามันจะทำให้ฉันประหลาดใจเล็กน้อยว่าคุณต้องทำทุกอย่างเพื่อทำสิ่งที่จำเป็นอย่างชัดเจนในบางกรณี
jcoder

50
แน่นอนคำสั่งเช่น ELEVATE หายไปอย่างชัดเจนในภาษาแบทช์ Windows
Matt

2
อาจจะง่ายขึ้นด้วย powershell ซึ่งดูเหมือนจะเป็นสคริปต์ lanaguge ที่ได้รับการอนุมัติสำหรับสิ่งที่ซับซ้อนมากขึ้น แต่ฉันไม่เคยใส่ใจที่จะเรียนรู้มันจนถึง :(
jcoder

1
ไวยากรณ์ใน powershell แตกต่างอย่างสิ้นเชิง (ไวยากรณ์คำกริยาคำนาม) แต่ช่วยให้คุณสามารถเรียกแอสเซมบลี. NET ได้อย่างง่ายดาย แต่มันก็ยากขึ้นนิดหน่อยที่จะจัดการกับมัน (การลงชื่อสคริปต์ ฯลฯ )
Matt

2
@Matt คุณสามารถตรวจสอบว่ามีความจริงบางอย่างที่อยู่เบื้องหลังคำตอบที่คุณปฏิเสธหรือไม่?
Artjom B.

41

ตามที่ 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

3
คุณถูกต้องถ้าติดตั้ง PowerShell คุณสามารถใช้มันเพื่อเรียกใช้ไฟล์แบตช์ด้วยระดับความสูง (ขอบคุณสำหรับตัวอย่างข้อมูล!) และใช่ไม่จำเป็นต้องใช้ฉลาก ขอบคุณสำหรับคำแนะนำมันมีค่า +1 ... :-)
Matt

2
เมื่อเรียกใช้จาก cmd Powershell.exe ไม่มีตัวเลือก -verb runas มันมีอยู่ถ้าคุณอยู่ใน PowerShell
Adil Hindistan

1
ฉันชอบโซลูชันนี้ใช้งานได้ดีสำหรับฉัน ใน Windows 8.1 ฉันต้องการ: label ของ gotPrivileges เพื่อให้ทำงานได้
ShaunO

ฉันกำลังตีปัญหาหากไฟล์แบตช์นี้อยู่ในระยะไกลบนเส้นทาง UNC
Ryan Beesley

ฉันเพิ่มไดเรกทอรีการเปลี่ยนแปลงเมื่อเริ่มต้นทำให้การไหลและทำความสะอาดง่ายขึ้น ไม่สามารถเปลี่ยนผู้ใช้ที่ทำงานผ่านWorkingDirectoryพารามิเตอร์ได้Start-Processเนื่องจากเหตุผลด้านความปลอดภัยในrunasกระบวนการ
ceztko

28

ฉันใช้คำตอบที่ยอดเยี่ยมของ 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

1
คำใบ้ดีสตีเฟ่น ดังนั้นสคริปต์ควรลงท้ายด้วยcd %~dp0เพื่อรักษาเส้นทางปัจจุบัน (ฉันถือว่างานนี้ใน Win7 เช่นกันดังนั้นคำสั่งเดียวกันสามารถใช้งานได้แม้ว่าจำเป็นเท่านั้นสำหรับ Win8 +) +1 สำหรับสิ่งนี้!
Matt

2
สิ่งนี้จำเป็นสำหรับระบบของฉันที่ใช้ Windows 7
meh-uk

1
หรือใช้pushd %~dp0แทน ... ทำไม เพราะpopd
Jaroslav Záruba

27

ฉันทำอย่างนี้:

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)

มีคำตอบมากมายในโพสต์นี้ฉันไม่รู้ด้วยซ้ำว่าจะเห็นคำตอบของฉันหรือไม่

อย่างไรก็ตามฉันพบว่าวิธีนี้ง่ายกว่าโซลูชันอื่น ๆ ที่เสนอในคำตอบอื่น ๆ ฉันหวังว่าจะช่วยใครบางคน


4
cd% ~ dp0 จะไม่ทำงานบนไดรฟ์เครือข่ายใช้ pushd% ~ dp0 แทน
Stavm

1
ฉันชอบความเรียบง่ายของคำตอบนี้ และในที่สุดก็มีเหตุผลที่จะใช้ Jscript!
โจ Coder

1
มายากล! ขอบคุณมาก.
Daniele Orlando

1
@ หมาป่าฉันพิมพ์คำตอบขนาดใหญ่เพียงเพื่อตระหนักว่าฉันเข้าใจผิดคุณ ... ฉันได้รับสิ่งที่คุณหมายถึงตอนนี้ /dฉันจะแก้ไขมันจะรวมถึง ขอบคุณเพื่อน :) (PS: นักเปียโนที่นี่ด้วย!)
Matheus Rocha

1
สิ่งนี้ใช้งานได้ดี แต่อาจเป็นความคิดที่ดีที่จะย้ายcdคำสั่งไปยังจุดเริ่มต้น (ซึ่งเป็นการยืนยันว่าพา ธ นั้นพร้อมใช้งานสำหรับสคริปต์ยกระดับด้วยเช่นกันมิฉะนั้นสคริปต์ยกระดับจะเรียกใช้จาก system32) คุณควรเปลี่ยนเส้นทางคำสั่ง net ไปที่ nul เพื่อซ่อนเอาต์พุต:net session >nul 2>&1
Nulano

23

แมตต์มีคำตอบที่ดี แต่มันก็ไม่สามารถโต้แย้งกันได้กับบท นี่คือการดัดแปลงของฉันที่เก็บข้อโต้แย้ง ฉันยังรวมการแก้ไขของสตีเฟ่นสำหรับปัญหาไดเรกทอรีการทำงานใน 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
นี่คือคำตอบที่มีประโยชน์ อย่างไรก็ตามในECHO UAC.ShellExecute....บรรทัด "batchArgs!"จะไม่ขยายตัวแปร "!batchArgs!"ใช้ การแก้ไขของฉันถูกปฏิเสธดังนั้นฉันจึงแสดงความคิดเห็น
หัวหอมบิน

1
@ fliedonion ด่างดี! ฉันไม่แน่ใจว่าทำไมการแก้ไขของคุณถูกปฏิเสธเพราะมันเป็นคำที่พิมพ์ผิดและการแก้ไขของคุณทำงาน ทำการเปลี่ยนแปลงด้วยตัวเองและทดสอบกับ Win 8.1 ตอนนี้เพื่อหาสคริปต์ทั้งหมดที่ฉันใช้รหัสนี้ ....
jxmallett

2
สคริปต์ที่ยากจนเมื่อใช้ข้อโต้แย้งอ้างเหมือนหรือtest.bat "a thing" "test script.bat" arg1 arg2แก้ไขแล้วทั้งหมด
jxmallett

ฉันจัดการเพื่อทำลายมัน (เนื่องจากความผิดของฉัน: การเรียกใช้สคริปต์จากไดรฟ์เครือข่ายที่แมปเนื่องจากผู้ดูแลระบบและผู้ใช้ปกติไม่มีแผนที่เดียวกัน) ยัง: มีวิธีดูผลลัพธ์หรือไม่ สำหรับฉันฉันต้องค้นหา. vbs และเปลี่ยน / c เป็น a / K จากนั้นดูด้วยตนเอง
Andreas Reiff

21

ฉันใช้ 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

ฉันคัดลอกวิธี 'ชื่อ Net' จากคำตอบของ @ Matt คำตอบของเขาเป็นเอกสารที่ดีขึ้นมากและมีข้อความผิดพลาดและไม่ชอบ อันนี้มีข้อได้เปรียบที่ PowerShell ติดตั้งแล้วและพร้อมใช้งานบน Windows 7 และสูงกว่า ไม่มีไฟล์ VBScript (* .vbs) ชั่วคราวและคุณไม่จำเป็นต้องดาวน์โหลดเครื่องมือ

วิธีการนี้ควรใช้งานได้โดยไม่มีการกำหนดค่าหรือการตั้งค่าใด ๆ ตราบใดที่สิทธิ์การใช้งาน PowerShell ของคุณไม่ถูกล็อค


เมื่อจัดทำรายการช่องว่างคั่นข้อโต้แย้งที่ล้อมรอบด้วยเครื่องหมายคำพูดเพื่อให้ถือว่าเป็น/c %~fnx0 %*'ส่วนหนึ่งส่วนที่ดูเหมือนจะออกจากทุกส่วนนอกเหนือจากครั้งแรก เช่นจากtest.bat "arg1 arg2 arg3"arg1 เท่านั้นจะถูกส่งต่อ
Nicolas Mommaerts

ดูเหมือนว่าไม่ว่าอะไรจะเกิดขึ้นกระบวนการเริ่มต้นจะลบเครื่องหมายคำพูดคู่ทั้งหมดในรายการอาร์กิวเมนต์ ..
Nicolas Mommaerts

ใช้งานได้สำหรับฉัน! netsh int set int %wifiname% Enable/Disableฉันใช้มันสำหรับ
Marslo

2
ฉันมีปัญหาเช่นเดียวกับ Nicolas Mommaerts ด้านบน ฉันไม่เข้าใจว่าทำไมมันถึงได้ผล (การแก้ไขที่ดีที่สุด) แต่การทำงานต่อไปนี้ควรทำ (โปรดสังเกตเครื่องหมายอัญประกาศพิเศษทั้งหมดในตอนท้าย): net file 1>nul 2>nul && goto :run || powershell -ex unrestricted -Command "Start-Process -Verb RunAs -FilePath '%comspec%' -ArgumentList '/c ""%~fnx0""""'"
quakes

ปัญหาอื่น (ความไม่สะดวก) คือสคริปต์หยุด (รอการป้อนข้อมูลจากผู้ใช้) หากบริการเซิร์ฟเวอร์ไม่ทำงาน (ฉันปิดใช้งานด้วยเหตุผล) ฉันมักจะทดสอบ perms ผู้ดูแลระบบโดยพยายามที่จะเขียนไปยังตำแหน่งไฟล์โฮสต์แต่มันอาจจะดีกว่าที่จะเรียกคำสั่ง powershell -Verb Runasแทนที่จะพึ่งพาบริการ windows ที่เปิดใช้งานหรือพยายามเขียนไฟล์
script'n'code

15

สำหรับบางโปรแกรมการตั้งค่า__COMPAT_LAYERตัวแปรสภาพแวดล้อมลับสุดยอดRunAsInvoker จะใช้งานได้ตรวจสอบสิ่งนี้:

set "__COMPAT_LAYER=RunAsInvoker"
start regedit.exe

แม้ว่าจะเป็นเช่นนี้จะไม่มี UAC แจ้งให้ผู้ใช้จะดำเนินการต่อโดยไม่มีสิทธิ์ผู้ดูแลระบบ


1
ลิงก์ไปยังไซต์ Microsoft ไม่ทำงานอีกต่อไปดังนั้นฉันจึงเปลี่ยนเป็นเนื้อหาใน archive.org หากใครสามารถหาลิงค์ที่ใช้งานได้ไปยังเนื้อหาในเว็บไซต์ของ Microsoft แต่ทั้งหมดหมายความว่าโปรดอัปเดตเป็น
RockPaperLizard

1
มันยังอยู่ในระดับกลางที่ไม่ได้ยกระดับดังนั้นคุณจึงไม่สามารถแก้ไข HKLM regeditได้ มันข้าม uac
HackingAddict1337

5

ฉันวางสิ่งนี้ไว้ในตอนต้นของสคริปต์:

:: 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
ฉันชอบการประมวลผลหาเรื่องในสคริปต์ของคุณ แต่โปรดทราบว่าcaclsเลิกใช้แล้วใน Windows 7 และ Windows ที่ใหม่กว่า
Matt

Fsutil สกปรกยิ่งดีกว่า
Wolf

1
คุณรู้หรือไม่ว่าบรรทัดนั้นpushd "%CD%"บันทึกไดเร็กทอรีการทำงานปัจจุบันและการเปลี่ยนแปลงเป็นไดเร็กทอรีการทำงานปัจจุบัน?
Wolf

3

ผมเขียนgsudo, สำหรับ Windows : ที่ยกในคอนโซลปัจจุบัน (บริบทไม่มีเปลี่ยนเป็นหน้าต่างใหม่) ด้วยการแคชข้อมูลประจำตัว (ลดลงป๊อบอัพ UAC) และยังยกคำสั่ง PowerShellsudoคำสั่ง

จะช่วยให้ยกระดับคำสั่งที่ต้องการสิทธิ์ผู้ดูแลระบบหรือทั้งชุดถ้าคุณต้องการ เพียงเติมเงินgsudo ก่อนสิ่งใดก็ตามที่จำเป็นต้องยกระดับ

ตัวอย่างไฟล์แบตช์ที่ยกระดับตัวเองโดยใช้ gsudo:

แก้ไข: ซับรุ่นใหม่หนึ่งที่ทำงานกับภาษาหน้าต่างใด ๆ และหลีกเลี่ยงปัญหา whoami :

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

ทางเลือก (รุ่นเดิม):

@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

ติดตั้ง:

  • ผ่าน chocolatey: choco install gsudo
  • หรือตัก: scoop install gsudo
  • หรือคว้ามันจาก GitHub: https://github.com/gerardog/gsudo

ดูการดำเนินการ gsudo: การสาธิต gsudo


เย็น. ขอบคุณ Windows รุ่นใดที่ใช้งานได้
RockPaperLizard

ชุดการทดสอบทำงานบนเซิร์ฟเวอร์ 2019 และกล่อง dev ภายในเครื่องของฉันคือ Windows 10 1909 ขออภัยฉันยังไม่ได้ทดสอบความเข้ากันได้กับระบบปฏิบัติการรุ่นเก่าอื่น ๆ
Gerardo Grignoli

ขอบคุณ Gerardo หากมีใครลองใช้กับ Windows รุ่นอื่น ๆ โปรดโพสต์ผลลัพธ์ของคุณ
RockPaperLizard

ฉันเพิ่งทดสอบ gsudo v0.7 บน Windows 8.1 และใช้งานได้ มันไม่สำคัญที่จะติดตั้งที่.Net Framework 4.6นั่น โชคดีที่choco install dotnet4.6.2นำมาซึ่งการพึ่งพายาก จากนั้นgsudo config Prompt "$p# "แก้ไขปัญหาเกี่ยวกับการConHostแสดงพรอมต์ที่ไม่ถูกต้อง (ตัวหนีลำดับอักขระแทนความคมชัดสีแดง) @RockPaperLizard
Gerardo Grignoli

ขอบคุณมาก Gerardo จะสามารถคอมไพล์ใหม่เพื่อทำงานกับ. Net Framework เวอร์ชันใดก็ได้ก่อน 4.6 หรือขึ้นอยู่กับฟังก์ชันการทำงานบางอย่างที่เฉพาะเจาะจงกับ 4.6?
RockPaperLizard

2

แม้ว่าจะไม่สามารถใช้ได้กับคำถามนี้โดยตรงเพราะต้องการข้อมูลบางอย่างสำหรับผู้ใช้ Google ก็พาฉันมาที่นี่เมื่อฉันต้องการเรียกใช้ไฟล์. bat ที่ยกระดับจากตัวกำหนดตารางงาน

วิธีที่ง่ายที่สุดคือการสร้างทางลัดไปยังไฟล์. bat เพราะสำหรับทางลัดคุณสามารถตั้งค่าRun as administratorได้โดยตรงจากคุณสมบัติขั้นสูง

เรียกใช้ช็อตคัตจากตัวกำหนดตารางงานเรียกใช้ไฟล์. bat ที่ยกระดับ


0

ใช้ PowerShell

หากไฟล์ cmd นั้นยาวฉันจะใช้อันแรกเพื่อต้องการระดับความสูงจากนั้นเรียกไฟล์ที่ทำงานจริง

หากสคริปต์เป็นคำสั่งง่าย ๆ ทุกอย่างอาจพอดีกับไฟล์ cmd ไฟล์เดียว อย่าลืมที่จะรวมเส้นทางในไฟล์สคริปต์

แม่แบบ:

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

ตัวอย่างที่ 1:

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

ตัวอย่างที่ 2:

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

0

ลองสิ่งนี้:

@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

หากคุณต้องการข้อมูลเกี่ยวกับไฟล์แบตช์นั้นให้เรียกใช้ HTML / JS / CSS Snippet:

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>


0

หากคุณไม่ต้องการส่งผ่านข้อโต้แย้งนี่คือสคริปต์กระตุ้นการใช้งาน UAC ขนาดกะทัดรัดที่มีความยาวบรรทัดเดียว นี่เป็นสิ่งที่คล้ายกันกับสคริปต์ยกระดับในคำตอบที่ได้รับการโหวตสูงสุด แต่ไม่ผ่านการโต้แย้งเนื่องจากไม่มีวิธีที่จะเข้าใจผิดได้ว่าจะจัดการกับชุดอักขระพิษทั้งหมดได้

@echo off
net sess>nul 2>&1||(echo(CreateObject("Shell.Application"^).ShellExecute"%~0",,,"RunAs",1:CreateObject("Scripting.FileSystemObject"^).DeleteFile(wsh.ScriptFullName^)>"%temp%\%~nx0.vbs"&start wscript.exe "%temp%\%~nx0.vbs"&exit)

:: Your batch file goes here

-3

ทางออกต่อไปนี้สะอาดและใช้งานได้ดี

  1. ดาวน์โหลดไฟล์ zip Elevate จากhttps://www.winability.com/download/Elevate.zip

  2. ภายใน zip คุณควรค้นหาสองไฟล์: Elevate.exe และ Elevate64.exe (หลังเป็นคอมไพล์ 64 บิตแบบดั้งเดิมหากคุณต้องการให้แม้ว่า Elevate.exe รุ่น 32 บิตปกติควรใช้งานได้ดีกับ Windows ทั้งรุ่น 32 และ 64 บิต)

  3. คัดลอกไฟล์ Elevate.exe ไปยังโฟลเดอร์ที่ Windows สามารถค้นหาได้เสมอ (เช่น C: / Windows) หรือคุณดีกว่าคุณสามารถคัดลอกในโฟลเดอร์เดียวกับที่คุณวางแผนที่จะเก็บไฟล์ค้างคาวของคุณ

  4. หากต้องการใช้งานในไฟล์แบตช์เพียงเติมคำสั่งที่คุณต้องการดำเนินการในฐานะผู้ดูแลระบบด้วยคำสั่งยกระดับเช่นนี้

 elevate net start service ...

2
คำสั่งนั้นจะเปิดไดอะล็อกที่เรียกว่าผู้ใช้ถ้าอนุญาตให้เรียกใช้งานคำสั่งนี้ได้ ดังนั้นคุณไม่สามารถใช้คำสั่งนี้ใน batchfile สิ่งที่ควรเรียกใช้โดยไม่มีการโต้ตอบกับผู้ใช้
Radon8472

หากเป็นไปได้ที่จะยกระดับโดยไม่ต้องมีปฏิสัมพันธ์กับผู้ใช้มันจะเป็นช่องโหว่ความปลอดภัยขนาดใหญ่ใช่ไหม? ไวรัสทุกตัวจะเริ่มใช้วิธีการนั้นเพื่อยกระดับตัวเองโดยไม่ได้รับอนุญาตจากผู้ใช้
Andrei Belogortseff
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.