Windows Batch 批次檔自動要求系統管理員權限

在批次檔開頭加幾行程式碼,執行時若沒有管理員權限就自動彈出 UAC 視窗重新啟動。

有些批次檔需要管理員權限才能正常執行,例如修改系統設定、操作受保護的資料夾、或是安裝服務。

相較於要求使用者以滑鼠右鍵「以系統管理員身份執行」,比較合理的做法是讓批次檔自己偵測權限,不足就直接觸發 UAC 提示重新啟動,因為最常發生的狀況就是直接啟動了腳本就被提示權限不足,使用體驗大打折扣。

做法

把以下程式碼貼在批次檔的最前面,Your codes 之後再接原本的邏輯:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
:: BatchGotAdmin (Run as Admin code starts)
REM --> Check for permissions
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.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 UAC.ShellExecute "%~s0", "", "", "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"
:: BatchGotAdmin (Run as Admin code ends)

:: Your codes should start from the following line

運作原理

  1. 偵測權限:用 cacls.exe 嘗試讀取 %SYSTEMROOT%\system32\config\system,這個檔案只有管理員才能存取。如果 errorlevel 不是 0,代表目前沒有管理員權限。

  2. 觸發 UAC:在 %temp% 建立一個暫時的 VBScript,內容是呼叫 Shell.ApplicationShellExecute 並指定 runas 動詞——這就是彈出 UAC 視窗的標準方式。VBScript 執行後,原本的 batch 程序直接 exit /B 結束,由新的提升後的 process 接手。

  3. 清理並繼續:取得權限後,刪除剛才建立的暫時 VBScript,然後 pushd 確保工作目錄正確,讓後續指令可以用相對路徑正常執行。

用在 PowerShell 腳本的啟動器

現在寫自動化腳本大多傾向用 PowerShell,.bat 檔案很常見的用途是當 .ps1 的啟動器——由 batch 負責提權、設定執行政策,再呼叫 PowerShell 腳本本體:

1
2
3
:: BatchGotAdmin (略,同上)

powershell.exe -ExecutionPolicy Bypass -File "%~dp0your-script.ps1"

為什麼不直接在 .ps1 裡觸發 UAC?其實 PowerShell 可以自我提權,寫法大概長這樣:

1
2
3
4
5
6
7
8
if (-NOT ([Security.Principal.WindowsPrincipal]
    [Security.Principal.WindowsIdentity]::GetCurrent()
).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
    Start-Process powershell.exe `
        "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" `
        -Verb RunAs
    Exit
}

但問題不在提權本身,主要有兩個獨立的阻礙:

第一:Execution Policy(主因)

Windows 客戶端預設的執行政策是 Restricted,直接禁止所有 .ps1 執行,不管是雙擊還是在命令列輸入路徑都一樣擋。企業環境還常透過 Group Policy 強制鎖定這個設定。.bat 啟動器可以在呼叫時帶入 -ExecutionPolicy Bypass 直接繞過,這是最主要的實際原因。

第二:雙擊不執行(獨立的安全設計)

即使 Execution Policy 已放寬,.ps1 雙擊預設也不會執行——Windows 把副檔名關聯設成用 PowerShell ISE(或其他關聯的 editor)開啟,而不是直接跑。Microsoft 文件明確指出這是刻意設計,與 Execution Policy 是兩件獨立的事。.bat 就沒有這個問題,雙擊直接執行。

兩個問題疊在一起,讓 .bat 作啟動器成為最省事的做法。

注意事項

  • UAC 提示會跳出一個獨立視窗,所以原本的 console 視窗會關掉、再開一個新的。如果有 console 輸出需要保留,注意這個行為。
  • %~s0 是批次檔自身的短路徑(8.3 格式),避免路徑含空白時 VBScript 解析出錯。
  • Windows 11 / 10 都適用,不需要額外安裝任何工具。

References

Licensed under CC BY-NC-SA 3.0 TW
最後更新 2026-05-06
comments powered by Disqus