如何在批处理文件中请求管理员访问


178

我试图编写一个批处理文件供我的用户使用UAC从其Vista机器上运行。该文件正在重写其主机文件,因此需要在具有管理员权限的情况下运行。我需要能够向他们发送一封电子邮件,其中包含指向.bat文件的链接。期望的行为是,当他们右键单击该文件并说“打开”时,他们将获得那些UAC对话框之一,该对话框使屏幕变黑并迫使他们回答是否要授予应用程序权限以管理员身份运行。相反,他们只是在命令行窗口中看到“拒绝访问”。

这有可能做不同的事情吗?


2
如果您遇到了这种情况,并且像我一样对使用PowerShell感到满意,请不要错过@ toster-cx的一线书。完善!
Michael Repucci '16

Answers:


351

这个脚本可以解决问题!只需将其粘贴到bat文件的顶部即可。如果要查看脚本的输出,请在批处理文件的底部添加“暂停”命令。

更新:现在对该脚本进行了稍微的编辑,以支持命令行参数和64位OS。

谢谢Eneerge @ https://sites.google.com/site/eneerge/scripts/batchgotadmin

@echo off

:: BatchGotAdmin
:-------------------------------------
REM  --> Check for permissions
    IF "%PROCESSOR_ARCHITECTURE%" EQU "amd64" (
>nul 2>&1 "%SYSTEMROOT%\SysWOW64\cacls.exe" "%SYSTEMROOT%\SysWOW64\config\system"
) ELSE (
>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"
    set params= %*
    echo UAC.ShellExecute "cmd.exe", "/c ""%~s0"" %params:"=""%", "", "runas", 1 >> "%temp%\getadmin.vbs"

    "%temp%\getadmin.vbs"
    del "%temp%\getadmin.vbs"
    exit /B

:gotAdmin
    pushd "%CD%"
    CD /D "%~dp0"
:--------------------------------------    
    <YOUR BATCH SCRIPT HERE>

22
我讨厌不得不做这个肮脏的dos批处理,但是有时候您被迫这样做,而且效果很好。干杯!
马特

4
此方法不转发参数。你知道怎么做吗?基本上,我观察到的是第一行%1具有一些值,而在最后一行%1为空。我需要提出论点。
插脚

3
就像FYI一样,它被测试为可以在Windows 8 Embedded中工作
Robert Snyder

6
这使我的机器陷入命令窗口的螺旋状,在整个屏幕上对角地打开和关闭。停止它的唯一方法是删除原始批处理文件。它反复运行我的批处理文件并写入vbs文件。第一次它要求授权,但是之后就循环了。
TomDestry

2
我在无限循环中遇到了与TomDestry完全相同的问题,并返回了代码2。这是在Windows 8.1上。我知道它可以在Windows 8.0上运行,并且不能确定是8.1更新还是引起问题的其他原因。对我有用的解决方案是不使用cacls.exe(或icacls),而是:net session> nul 2>&1如果ERRORLEVEL 1 goto UACPrompt ...
修改了2014年

55

这是我一直使用的单线:

@echo off
if not "%1"=="am_admin" (powershell start -verb runas '%0' am_admin & exit /b)

echo main code here
pause

笔记:

  • 仅在Windows 7和10上进行了测试,您可能不得不弄乱报价
  • 目前不支持传递参数

1
如果您知道可以有多少个参数,则可以通过在参数之后加上参数来传递参数am_admin if not "%1"=="am_admin" (powershell start -verb runas '%0' 'am_admin "%~1" "%~2"' & exit)。参数将是其所在位置之上的参数
Tony Brix

也可以用来'am_admin %*'传递所有内容,不适用于双引号和空格tho:/您可以shift批量使用弹出第一个arg,从而修复除以外的所有arg %0
toster-cx

这是一个很好的答案,但是不应该被接受,因为它不会检查在第一次运行时是否以ADMIN特权运行。
T.Todua

要保留工作目录,请cd /D %~dp0if not "%1"=="am_admin" (powershell start -verb runas '%0' am_admin & exit /b)
Pedro Duarte

好答案。即使在具有%temp%的写入权限的情况下,VB脚本事物创建无限循环时,它也可以简单地工作。
Twonky

19

这是我的代码!它看起来很大,但主要是注释行(以::开头的行)。

特征:

  • 全参数转发
  • 不更改工作文件夹
  • 错误处理
  • 接受带括号的路径(%TEMP%文件夹除外)
  • 支持UNC路径
  • 映射的文件夹检查(如果管理员无法访问映射的驱动器,则警告您)

  • 可以用作外部库(在以下主题中查看我的文章: https //stackoverflow.com/a/30417025/4932683

  • 可以在代码中的任何地方/需要时调用

只需将其附加到批处理文件的末尾,或将其另存为库(请参见上文)

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:RequestAdminElevation FilePath %* || goto:eof
:: 
:: By:   Cyberponk,     v1.5 - 10/06/2016 - Changed the admin rights test method from cacls to fltmc
::          v1.4 - 17/05/2016 - Added instructions for arguments with ! char
::          v1.3 - 01/08/2015 - Fixed not returning to original folder after elevation successful
::          v1.2 - 30/07/2015 - Added error message when running from mapped drive
::          v1.1 - 01/06/2015
:: 
:: Func: opens an admin elevation prompt. If elevated, runs everything after the function call, with elevated rights.
:: Returns: -1 if elevation was requested
::           0 if elevation was successful
::           1 if an error occured
:: 
:: USAGE:
:: If function is copied to a batch file:
::     call :RequestAdminElevation "%~dpf0" %* || goto:eof
::
:: If called as an external library (from a separate batch file):
::     set "_DeleteOnExit=0" on Options
::     (call :RequestAdminElevation "%~dpf0" %* || goto:eof) && CD /D %CD%
::
:: If called from inside another CALL, you must set "_ThisFile=%~dpf0" at the beginning of the file
::     call :RequestAdminElevation "%_ThisFile%" %* || goto:eof
::
:: If you need to use the ! char in the arguments, the calling must be done like this, and afterwards you must use %args% to get the correct arguments:
::      set "args=%* "
::      call :RequestAdminElevation .....   use one of the above but replace the %* with %args:!={a)%
::      set "args=%args:{a)=!%" 
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEDELAYEDEXPANSION & set "_FilePath=%~1"
  if NOT EXIST "!_FilePath!" (echo/Read RequestAdminElevation usage information)
  :: UAC.ShellExecute only works with 8.3 filename, so use %~s1
  set "_FN=_%~ns1" & echo/%TEMP%| findstr /C:"(" >nul && (echo/ERROR: %%TEMP%% path can not contain parenthesis &pause &endlocal &fc;: 2>nul & goto:eof)
  :: Remove parenthesis from the temp filename
  set _FN=%_FN:(=%
  set _vbspath="%temp:~%\%_FN:)=%.vbs" & set "_batpath=%temp:~%\%_FN:)=%.bat"

  :: Test if we gave admin rights
  fltmc >nul 2>&1 || goto :_getElevation

  :: Elevation successful
  (if exist %_vbspath% ( del %_vbspath% )) & (if exist %_batpath% ( del %_batpath% )) 
  :: Set ERRORLEVEL 0, set original folder and exit
  endlocal & CD /D "%~dp1" & ver >nul & goto:eof

  :_getElevation
  echo/Requesting elevation...
  :: Try to create %_vbspath% file. If failed, exit with ERRORLEVEL 1
  echo/Set UAC = CreateObject^("Shell.Application"^) > %_vbspath% || (echo/&echo/Unable to create %_vbspath% & endlocal &md; 2>nul &goto:eof) 
  echo/UAC.ShellExecute "%_batpath%", "", "", "runas", 1 >> %_vbspath% & echo/wscript.Quit(1)>> %_vbspath%
  :: Try to create %_batpath% file. If failed, exit with ERRORLEVEL 1
  echo/@%* > "%_batpath%" || (echo/&echo/Unable to create %_batpath% & endlocal &md; 2>nul &goto:eof)
  echo/@if %%errorlevel%%==9009 (echo/^&echo/Admin user could not read the batch file. If running from a mapped drive or UNC path, check if Admin user can read it.)^&echo/^& @if %%errorlevel%% NEQ 0 pause >> "%_batpath%"

  :: Run %_vbspath%, that calls %_batpath%, that calls the original file
  %_vbspath% && (echo/&echo/Failed to run VBscript %_vbspath% &endlocal &md; 2>nul & goto:eof)

  :: Vbscript has been run, exit with ERRORLEVEL -1
  echo/&echo/Elevation was requested on a new CMD window &endlocal &fc;: 2>nul & goto:eof
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

使用方法示例

:EXAMPLE
@echo off

 :: Run this script with elevation
 call :RequestAdminElevation "%~dpfs0" %* || goto:eof

  echo/I now have Admin rights!
  echo/
  echo/Arguments using %%args%%:    %args%
  echo/Arguments using %%*: %*
  echo/%%1= %~1
  echo/%%2= %~2
  echo/%%3= %~3

  echo/
  echo/Current Directory: %CD%
  echo/
  echo/This file: %0
  echo/

pause &goto:eof

[here you paste the RequestAdminElevation function code]

效果很好,但我不得不更改一条线才能使其正常工作。将&fc;: 2>nulset "_FN=_%~ns1" & echo/%TEMP%| findstr /C:"(" >nul && (echo/ERROR: %%TEMP%% path can not contain parenthesis &pause &endlocal &fc;: 2>nul & goto:eof)是在错误级别设置为1,我删除了该位,它的工作完美。我正在使用Windows 10 Home。
克尼里(Knyri)2013年

您的%temp%文件夹的路径中是否带有括号?仅在这种情况下,才应设置错误级别1。
cyberponk

不。它需要fc;::eof之后吗?我不确定为什么也有可能导致此问题,因为它应该得到执行。
克尼里(Knyri)2016年

故意在退出前设置“ fc ;: 2> nul”以指示错误级别1。您能否取消@echo并运行,然后将输出以私人消息形式发送给我?谢谢!
cyberponk

无论如何,echo/%TEMP%| findstr /C:"(" >nul测试环境变量中是否存在(字符%temp%,并且仅应在&&if正数之后运行该部分。奇怪的是为什么您的(测试却返回阳性。
cyberponk

7

另一种方法是

  • 在本地创建快捷方式并将其设置为调用管理员权限[属性,高级,以管理员身份运行]

然后

  • 向您的用户发送快捷方式[或快捷方式的链接,而不是批处理文件本身的链接]。

丹尼斯

[此后添加-是的,我确实没有注意到此主题的日期。]


6

Ben Gripka的解决方案导致无限循环。他的批处理如下(伪代码):

IF "no admin privileges?"
    "write a VBS that calls this batch with admin privileges"
ELSE
    "execute actual commands that require admin privileges"

如您所见,如果VBS请求管理员特权失败,则会导致无限循环。

但是,尽管已经成功请求了管理员特权,但仍可能发生无限循环。

Ben Gripka的批处理文件中的检查很容易出错。我进行了批处理,发现尽管检查失败,但仍具有管理员权限。有趣的是,如果我从Windows资源管理器启动了批处理文件,则检查按预期进行了,但是当我从IDE启动该文件时却没有。

因此,我建议使用两个单独的批处理文件。第一个生成调用第二个批处理文件的VBS:

@echo off

echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
set params = %*:"=""
echo UAC.ShellExecute "cmd.exe", "/c ""%~dp0\my_commands.bat"" %params%", "", "runas", 1 >> "%temp%\getadmin.vbs"

"%temp%\getadmin.vbs"
del "%temp%\getadmin.vbs"

第二个名为“ my_commands.bat”,与第一个位于同一目录中,包含您的实际命令:

pushd "%CD%"
CD /D "%~dp0"
REM Your commands which require admin privileges here

这不会引起无限循环,并且还消除了易于出错的管理员特权检查。


为您工作?对于我而言,可悲的是,由于相同的潜在问题,此线程以及所有其他线程以及其他线程中的线程失败。每当从另一个程序内部间接创建Shell对象时,“ runas” parm(或命令)就会失败。感兴趣的话题在这里
Laurie Stearn '18

为我工作:)
Sritam Jagadev '19

6

另一个PowerShell解决方案...

这不是关于以管理员身份运行批处理脚本,而是如何从批处理中提升另一个程序...

我有一个exe批处理文件“包装器”。它们具有相同的“根文件名”,但具有备用扩展名。我能够以admin身份启动exe,并将工作目录设置为包含脚本的目录,并通过以下一行 powershell调用:

@powershell "Start-Process -FilePath '%~n0.exe' -WorkingDirectory '%~dp0' -Verb RunAs"

更多信息

Start-Process您还可以申请很多其他选择!退房: https //docs.microsoft.com/zh-cn/powershell/module/microsoft.powershell.management/start-process?view=powershell-6

请注意,我使用@前缀。这相当于@echo off一行。我%~n0在这里使用以获得批处理脚本的“根名称”,然后.exe将其串联以指向相邻的二进制文件。的使用%~dp0提供了批处理所在目录的完整路径。当然,-Verb RunAs参数提供了height


4

我知道这不是OP的解决方案,但是由于我确定这里还有许多其他用例,所以我想我会分享。

我在这些答案中的所有代码示例都遇到了问题,但后来发现: http //www.robotronic.de/runasspcEn.html

它不仅允许您以管理员身份运行,而且还检查文件以确保其未被篡改并安全地存储所需的信息。我承认这不是弄清楚如何使用的最明显的工具,但是对于我们这些编写代码的人来说,它应该足够简单。


3

@echo off并且title可以来此代码之前:

net session>nul 2>&1
if %errorlevel%==0 goto main
echo CreateObject("Shell.Application").ShellExecute "%~f0", "", "", "runas">"%temp%/elevate.vbs"
"%temp%/elevate.vbs"
del "%temp%/elevate.vbs"
exit

:main
    <code goes here>
exit

如果您不需要担心以下事项,那么很多其他答案都是过分的:

  • 参量
  • 工作目录(cd %~dp0将更改为包含批处理文件的目录)

2
@echo off 
Net session >nul 2>&1 || (PowerShell start -verb runas '%~0' &exit /b)
Echo Administrative privileges have been got. & pause

以上适用于我的Windows 10版本1903


1

由于我对此脚本有麻烦,因此会无限循环地(使用Win 7 Pro)弹出一个新的命令提示符,并再次运行,因此建议您尝试另一种方法:如何自动提升批处理文件,以便它可以从是否需要UAC管理员权限?

请注意,您必须按照编辑中的说明在脚本末尾添加它,以便在特权提升后返回脚本目录:cd / d%〜dp0


检查我对这个问题的回答。它处理所有这些问题。
cyberponk '02

1

基于toster-cx的帖子和本页上其他有趣的帖子,我对如何配置和解决问题有了深刻的了解。我有一个类似的问题,我希望“磁盘清理”实用程序每周一次在星期一和星期四的午餐时间(例如下午2点)运行两次。但是,这需要提高权限。

共享批处理文件可能会对像我这样的其他初学者有所帮助-

@echo off
echo  Welcome to scheduling 'PC Maintenance Activity'
ping localhost -n 3 >nul
echo -- Step - 1 of 3 : Please give 'Admin' rights on next screen
ping localhost -n 5 >nul
if not "%1"=="am_admin" (powershell start -verb runas '%0' am_admin & exit)
cls
echo -- Step - 2 of 3 : In next screen, select temp areas for cleaning 
during routine scheduled activity
ping localhost -n 3 >nul
C:\Windows\System32\cleanmgr.exe /sageset:112
cls
echo    Now scheduling maintenance activity...
SchTasks /Create /SC WEEKLY /D MON,THU /TN PC_Cleanup /TR 
"C:\Windows\System32\cleanmgr.exe "/sagerun:112 /ST 14:00

cls

echo                         -- Thanks for your co-operation --
echo                    -- Maintenance activity is scheduled for --
echo                       -- Every Monday and Thursday at 2 pm --

ping localhost -n 10 >nul

非常感谢这个论坛和Rems POST在这里[ https://www.petri.com/forums/forum/windows-scripting/general-scripting/32313-schtasks-exe-need-to-pass-parameters-to-script ] [1]

他的帖子有助于安排任务时配置可选参数。


1

这篇文章中还有FSUTIL查询,它也链接到ss64.com,具有以下代码:

@Echo Off
Setlocal
:: First check if we are running As Admin/Elevated
FSUTIL dirty query %SystemDrive% >nul
if %errorlevel% EQU 0 goto START

::Create and run a temporary VBScript to elevate this batch file
   Set _batchFile=%~f0
   Set _Args=%*
   :: double up any quotes
   Set _batchFile=""%_batchFile:"=%""
   Set _Args=%_Args:"=""%

   Echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\~ElevateMe.vbs"
   Echo UAC.ShellExecute "cmd", "/c ""%_batchFile% %_Args%""", "", "runas", 1 >> "%temp%\~ElevateMe.vbs"

   cscript "%temp%\~ElevateMe.vbs" 
   Exit /B

:START
:: set the current directory to the batch file location
cd /d %~dp0
:: Place the code which requires Admin/elevation below
Echo We are now running as admin [%1] [%2]
pause

只要有FSUTIL,它就是一个可靠的选择。


0

您不能从批处理文件中请求管理员权限,但是可以在%temp%中编写Windows脚本宿主脚本并运行该脚本(然后以admin身份执行批处理)。要在Shell中调用ShellExecute方法。以“ runas”为动词的应用程序对象


0

使用mshta提示输入管理员权限:

@echo off
net session >nul 2>&1 && goto :admintasks
MSHTA "javascript: var shell = new ActiveXObject('shell.application'); shell.ShellExecute('%~nx0', '', '', 'runas', 1);close();"
exit /b
:admintasks
rem ADMIN TASKS HERE

或者,使用powershell:

powershell -c Start-Process "%~nx0" -Verb runas

-5

使用runas命令。但是,我认为您无法通过电子邮件轻松发送.bat文件。


6
这个答案是不正确的。该runas命令不能用于引发高程。
Bill_Stewart '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.