如何以提升的权限运行批处理文件命令?

如何以提升的权限运行批处理文件命令?

我正在编写一个批处理文件,将分发给用户。我需要以提升的权限运行一些命令。我最初的解决方案是使用:

runas /noprofile /user:Administrator SOME_COMMAND  

但是许多机器(包括我的机器)的隐藏管理员帐户处于非活动状态,因此没有设置管理员密码。我也不能指定其他用户名,因为不同的机器会有不同的用户。有没有办法通过批处理文件复制“右键单击 -> 以管理员身份运行”操作?我不介意弹出提示,我只是不希望用户明确右键单击并以管理员身份运行。

答案1

您可以利用每个现代 Windows 系统上都存在的 PowerShell。

将需要提升权限的命令拆分为单独的批处理文件,例如elevated.bat。然后,在运行它们时,从非提升权限的脚本中使用它:

powershell -command "Start-Process elevated.bat -Verb runas"

-Verb runas部分是导致提升权限提示的原因。如果原始批处理文件已经以管理员身份运行,或者 UAC 提示已关闭,则新文件将在没有提示的情况下提升权限。

请注意,提升的批处理器的当前目录将以 开始System32。如果这是一个问题,您可以使用此替代版本让它在与非提升脚本相同的目录中启动:

powershell -command "Start-Process cmd -ArgumentList '/c cd /d %CD% && elevated.bat' -Verb runas"

这会导致新cmd实例首先cd进入未提升的提示符变量提供的目录%CD%,然后执行所需的批处理文件。

答案2

运行管理员让您以提升的权限从命令行运行程序(它将显示 UAC,以便用户可以输入凭据)。

答案3

继续 Ben N 的回答:

为了使批处理脚本自动提升(如果未提升权限启动则自动以管理员身份重新启动),您可以在脚本中首先使用以下代码(这里我用它来FSUTIL DIRTY query测试管理员权限)。

FSUTIL DIRTY query %SystemDrive% >NUL || (
    PowerShell "Start-Process -FilePath '%0' -Verb RunAs"
    EXIT
)

REM Main code here

或者,如果您的脚本要求工作目录与批处理文件位置相同,请使用:

FSUTIL DIRTY query %SystemDrive% >NUL || (
    PowerShell "Start-Process -FilePath cmd.exe -Args '/C CHDIR /D %CD% & "%0"' -Verb RunAs"
    EXIT
)

REM Main code here

答案4

抱歉,我的英语很糟糕。这将以提升权限(具有管理员权限)运行批处理文件。此脚本由 Matt 创建(https://stackoverflow.com/users/1016343/matt)我修改了 Matt 脚本。更新:添加了 Windows 系统文件夹检查器。脚本:

::::::::::::::::::::::::::::::::::::::::::::
:: Elevate.cmd - Version 4
:: Automatically check & get admin rights
:: see "https://stackoverflow.com/a/12264592/1016343" for description
:: Sorry for very bad english
:: Modified script. Added check windows
:: system folder and then add it to ENV
:: (Envronment Variable)
::::::::::::::::::::::::::::::::::::::::::::
 @echo off
 CLS
 ECHO.
 ECHO =============================
 ECHO Running Admin shell
 ECHO =============================

:init
 setlocal DisableDelayedExpansion
 set cmdInvoke=1
 
:checkWinSys
 set "ResultFile=%temp%\checkSysResult.txt"
 if exist "%SystemRoot%\Sysnative" (
 echo 1
 goto checkSysResult
 ) > "%ResultFile%"

 if exist "%SystemRoot%\System32" (
 echo 2
 goto checkSysResult
 ) > "%ResultFile%"

 setlocal EnableDelayedExpansion

 set count=0

 for /f "tokens=*" %%x in (%ResultFile%) do (
     set /a count+=1
     set var[!count!]=%%x
 )

:checkSysResult
 if "%var[3]%"=="1" ( set winSysFolder=Sysnative & goto skip ) else ( set winSysFolder=System32 & goto skip )

:skip
 del "%ResultFile%"
 setlocal DisableDelayedExpansion

:init(1)
 set "batchPath=%~0"
 for %%k in (%0) do set batchName=%%~nk
 set "vbsGetPrivileges=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 & pushd .
 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

相关内容