Featured image of post Windows .bat 自动申请UAC

Windows .bat 自动申请UAC

The simplest way & essential best practices of achieving UAC elevation in batch script.

为了自动化电脑任务,可以使用各种程式,而系统原生的bat(Windows)或sh(Linux)指令码就是最通用最佳的选择。

管理员权限是执行各类电脑任务经常碰到的问题,OS自动弹出的权限申请并不总和预先以管理员权限执行表现一致,比如 Office Deploy Tool 某次更新后就不能在指令码执行时弹出的UAC确认后回到正常路径。

本文介绍指令码自动申请UAC的建议方法和最佳实践。

借助PowerShell

目前主流的Windows10/11都预装了功能强大的 PowerShell,最简单的方法就是用 PowerShell 指令包装指令码档案从管理员权限运行,而将申请UAC的过程交给稳定的 PowerShell 执行。

powershell Start-Process -Verb RunAs -FilePath 执行.exe -ArgumentList """原指令的后续部分"""

例如:

1
powershell Start-Process -Verb RunAs -FilePath setup.exe -ArgumentList """/configure LTSC2024.xml"""

无副作用最佳实践

对于复杂的嵌套的bat程式,自动申请UAC就需要提前检测是否已有管理员权限。 检测过程也不应操作文件系统,留下副作用,毕竟创建临时文件再删除不能在任何情况下都权限足够顺利消除副作用。 自动申请UAC可能用于各种情况,最好不要依赖哪怕 PowerShell 等外部程序。 下面的bat代码片段可以无副作用的检测权限,自动申请UAC,并维持全部指令码的生命周期。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
@echo off
REM :::::::::::::::::::::::::::::::::::::::::
REM Elevate.cmd - Version 9
REM Automatically check & get admin rights
REM see "https://stackoverflow.com/a/12264592/1016343" for description
REM :::::::::::::::::::::::::::::::::::::::::
 
 CLS
 ECHO/
 ECHO =============================
 ECHO Running Admin shell
 ECHO =============================

:init
  setlocal EnableExtensions DisableDelayedExpansion
  set cmdInvoke=1
  set winSysFolder=System32
  set "batchPath=%~f0"
  rem this works also from cmd shell, other than %~0
  for %%k in (%0) do set batchName=%%~nk
  set "vbsGetPrivileges=%temp%\OEgetPriv_%batchName%.vbs"
  setlocal EnableDelayedExpansion

:checkPrivileges
  %SystemRoot%\System32\whoami.exe /groups /nh | %SystemRoot%\System32\find.exe "S-1-16-12288" 1>nul
  if errorlevel 1 goto getPrivileges

:checkPrivileges2
  %SystemRoot%\System32\net.exe session 1>nul 2>NUL
  if not errorlevel 1 goto gotPrivileges

: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)

  REM :::::::::::::::::::::::::
  REM START
  REM :::::::::::::::::::::::::
  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 %1 %2 %3 %4 %5 %6 %7 %8 %9

https://stackoverflow.com/questions/7044985/how-can-i-auto-elevate-my-batch-file-so-that-it-requests-from-uac-administrator

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy