Có một cách dễ dàng mà không cần sử dụng công cụ bên ngoài - nó chạy tốt với Windows 7, 8, 8.1 và 10 và cũng tương thích ngược (Windows XP không có bất kỳ UAC nào, do đó không cần độ cao - trong đó trường hợp kịch bản chỉ tiến hành).
Kiểm tra mã này (Tôi lấy cảm hứng từ mã do NIronwolf đăng trong chuỗi Batch File - "Truy cập bị từ chối" trên Windows 7? ), Nhưng tôi đã cải thiện nó - trong phiên bản của tôi không có thư mục nào được tạo và xóa kiểm tra các đặc quyền của quản trị viên):
::::::::::::::::::::::::::::::::::::::::::::
:: 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
Kịch bản lợi dụng thực tế NET FILE
đòi hỏi đặc quyền của quản trị viên và trả về errorlevel 1
nếu bạn không có nó. Độ cao đạt được bằng cách tạo một tập lệnh khởi chạy lại tệp bó để có được các đặc quyền. Điều này khiến Windows xuất hiện hộp thoại UAC và yêu cầu bạn cung cấp tài khoản và mật khẩu quản trị viên.
Tôi đã thử nghiệm nó với Windows 7, 8, 8.1, 10 và với Windows XP - nó hoạt động tốt cho tất cả. Ưu điểm là, sau điểm bắt đầu, bạn có thể đặt bất cứ thứ gì yêu cầu đặc quyền của quản trị viên hệ thống, ví dụ, nếu bạn có ý định cài đặt lại và chạy lại dịch vụ Windows cho mục đích gỡ lỗi (giả sử mypackage.msi là gói cài đặt dịch vụ) :
msiexec /passive /x mypackage.msi
msiexec /passive /i mypackage.msi
net start myservice
Nếu không có tập lệnh nâng cao đặc quyền này, UAC sẽ hỏi bạn ba lần về mật khẩu và người dùng quản trị viên của bạn - bây giờ bạn chỉ được hỏi một lần khi bắt đầu và chỉ khi được yêu cầu.
Nếu tập lệnh của bạn chỉ cần hiển thị thông báo lỗi và thoát nếu không có bất kỳ đặc quyền quản trị viên nào thay vì tự động nâng cao, thì điều này thậm chí còn đơn giản hơn: Bạn có thể đạt được điều này bằng cách thêm vào phần sau của tập lệnh:
@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 ...
Bằng cách này, người dùng phải nhấp chuột phải và chọn "Chạy với tư cách quản trị viên" . Kịch bản sẽ tiến hành sau REM
câu lệnh nếu phát hiện quyền quản trị viên, nếu không thì thoát với lỗi. Nếu bạn không yêu cầu PAUSE
, chỉ cần loại bỏ nó.
Quan trọng: NET FILE [...] EXIT /D)
phải trên cùng một dòng. Nó được hiển thị ở đây trong nhiều dòng để dễ đọc hơn!
Trên một số máy, tôi đã gặp phải sự cố đã được giải quyết trong phiên bản mới ở trên. Một là do xử lý trích dẫn kép khác nhau và vấn đề còn lại là do UAC bị vô hiệu hóa (được đặt ở mức thấp nhất) trên máy Windows 7, do đó tập lệnh tự gọi đi gọi lại.
Bây giờ tôi đã sửa lỗi này bằng cách tước các trích dẫn trong đường dẫn và thêm lại chúng sau đó và tôi đã thêm một tham số bổ sung được thêm vào khi tập lệnh khởi chạy lại với quyền nâng cao.
Các trích dẫn kép được loại bỏ bằng cách sau đây (chi tiết ở đây ):
setlocal DisableDelayedExpansion
set "batchPath=%~0"
setlocal EnableDelayedExpansion
Sau đó bạn có thể truy cập đường dẫn bằng cách sử dụng !batchPath!
. Nó không chứa bất kỳ dấu ngoặc kép nào, vì vậy có thể an toàn để nói "!batchPath!"
sau trong tập lệnh.
Dòng
if '%1'=='ELEV' (shift & goto gotPrivileges)
kiểm tra xem tập lệnh đã được tập lệnh VBScript gọi để nâng cao quyền hay chưa, do đó tránh được sự thu hồi vô tận. Nó loại bỏ tham số bằng cách sử dụng shift
.
Cập nhật:
Để tránh phải đăng ký .vbs
tiện ích mở rộng trong Windows 10 , tôi đã thay thế dòng này
"%temp%\OEgetPrivileges.vbs"
bằng
"%SystemRoot%\System32\WScript.exe" "%temp%\OEgetPrivileges.vbs"
đoạn script trên; cũng được thêm vào cd /d %~dp0
theo đề xuất của Stephen (câu trả lời riêng) và Tomáš Zato (bình luận) để đặt thư mục script làm mặc định.
Bây giờ kịch bản vinh danh các tham số dòng lệnh được truyền cho nó. Cảm ơn jxmallet, TanisDLJ và Peter Mortensen đã quan sát và truyền cảm hứng.
Theo gợi ý của Artjom B., tôi đã phân tích nó và đã thay thế SHIFT
bằng SHIFT /1
, nó giữ nguyên tên tệp cho %0
tham số
Thêm del "%temp%\OEgetPrivileges_%batchName%.vbs"
vào :gotPrivileges
phần để làm sạch (như MLT gợi ý). Đã thêm %batchName%
để tránh tác động nếu bạn chạy các lô khác nhau song song. Lưu ý rằng bạn cần sử dụng for
để có thể tận dụng các hàm chuỗi nâng cao, chẳng hạn như %%~nk
, chỉ trích xuất tên tệp.
Cấu trúc tập lệnh được tối ưu hóa, các cải tiến (biến được thêm vbsGetPrivileges
hiện được tham chiếu ở mọi nơi cho phép dễ dàng thay đổi đường dẫn hoặc tên của tệp, chỉ xóa .vbs
tệp nếu cần nâng cao lô)
Trong một số trường hợp, một cú pháp gọi khác nhau được yêu cầu cho độ cao. Nếu tập lệnh không hoạt động, hãy kiểm tra các tham số sau:
set cmdInvoke=0
set winSysFolder=System32
Thay đổi tham số thứ 1 thành set cmdInvoke=1
và kiểm tra xem điều đó đã khắc phục sự cố chưa. Nó sẽ thêm cmd.exe
vào kịch bản thực hiện độ cao.
Hoặc cố gắng thay đổi tham số thứ 2 thành winSysFolder=Sysnative
, điều này có thể giúp ích (nhưng trong hầu hết các trường hợp không bắt buộc) trên các hệ thống 64 bit. (ADBailey đã báo cáo điều này). "Sysnative" chỉ được yêu cầu để khởi chạy các ứng dụng 64 bit từ máy chủ tập lệnh 32 bit (ví dụ: quy trình xây dựng Visual Studio hoặc gọi tập lệnh từ ứng dụng 32 bit khác).
Để làm rõ hơn về cách các tham số được diễn giải, tôi hiện đang hiển thị nó như thế nào P1=value1 P2=value2 ... P9=value9
. Điều này đặc biệt hữu ích nếu bạn cần kèm theo các tham số như đường dẫn trong dấu ngoặc kép, vd "C:\Program Files"
.
Nếu bạn muốn gỡ lỗi tập lệnh VBS, bạn có thể thêm //X
tham số vào WScript.exe làm tham số đầu tiên, như được đề xuất ở đây (nó được mô tả cho CScript.exe, nhưng cũng hoạt động với WScript.exe).
Liên kết hữu ích: