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

skb*_*skb 165 command-line uac batch-file elevated-privileges

我正在尝试为我的用户编写一个批处理文件,以便在他们的Vista机器上运行UAC.该文件正在重写其hosts文件,因此需要以管理员权限运行.我需要能够向他们发送一封包含.bat文件链接的电子邮件.所需的行为是,当他们右键单击文件并说"打开"时,他们将获得其中一个UAC对话框,使屏幕变暗并强制他们回答是否要授予应用程序以管理员身份运行的权限.相反,他们只是在命令行窗口看到"拒绝访问".

这可能有不同的做法吗?

Ben*_*pka 326

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

更新:此脚本现在稍微编辑,以支持命令行参数和64位操作系统.

谢谢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>
Run Code Online (Sandbox Code Playgroud)

  • 我讨厌不得不做这个污秽的批处理废话,但有时你被迫,这很有效.干杯! (19认同)
  • 这使我的机器进入一个螺旋形的命令窗口,在屏幕上对角地打开和关闭.阻止它的唯一方法是删除原始批处理文件.它反复运行我的批处理文件并编写vbs文件.它第一次要求授权,但之后它只是循环. (5认同)
  • 此方法不转发参数.你知道怎么做吗?基本上我观察到的是,在第一行%1有一些值,在最后一行%1为null.我需要转发论点. (4认同)
  • 没有为我工作,但http://stackoverflow.com/a/28467343/586754工作. (4认同)
  • 正如FYI一样,它在Windows 8 Embedded中进行了测试 (3认同)
  • 我遇到了与TomDestry完全相同的问题,带有无限循环并返回代码2.这是在Windows 8.1上.我知道它在Windows 8.0上有效,并且无法确定它是8.1更新还是导致isssue的其他内容.对我有用的解决方案是不使用cacls.exe(或icacls),而是:net session> nul 2>&1 IF ERRORLEVEL 1转到UACPrompt ... (2认同)
  • 我想知道应该在'set params =%*:"=""`这一行中发生什么.有人可以向我解释这里发生了什么吗?对于初学者来说,`%params%`不会被分配,因为在等号之前有一个额外的空格.然后看起来最后还有一个额外的引用.这是否有目的? (2认同)
  • 实际上,等等......上面没有按预期工作......就像我说的那样,它没有通过论证......我仍在寻找解决方案(虽然不介意帮助).原因显然是由于某种原因,引用替换导致空字符串. (2认同)
  • 修复了关于参数保存的主要错误。我通常不会对其他用户的答案进行如此实质性的更改。但是这个公认的答案对很多人来说显然很重要,并且自 2013 年 1 月以来一直被窃听,当时 OP 试图增强代码以保留参数。可以在 https://superuser.com/a/1249855/109090 上找到该错误和修复的完整说明 (2认同)
  • @rahuldottech - 如果没有传递参数,我对保存参数的修复有一个bug.params var将是未定义的,因此引用倍增代码将导致不平衡的parens,这将逃避重定向.我使用`set params =%*`而不是`set params =%*`来修复代码,因此保证定义params (2认同)

tos*_*-cx 44

这是我一直在使用的单线程:

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

echo main code here
pause
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 只在Windows 7和10上测试过,你可能不得不搞乱报价
  • 暂时不支持传递参数

  • 要保留工作目录,请在 `if not "%1"=="am_admin" (powershell start -verb runas '%0' am_admin &amp; exit /b)` 之后添加 `cd /D %~dp0` (2认同)

cyb*_*onk 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
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Run Code Online (Sandbox Code Playgroud)

关于如何使用它的示例

: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]
Run Code Online (Sandbox Code Playgroud)


小智 7

另一种方法是

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

然后

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

丹尼斯

[之后添加 - 是的,我没有注意到这个帖子的日期.]


fis*_*one 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"
Run Code Online (Sandbox Code Playgroud)

如您所见,如果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"
Run Code Online (Sandbox Code Playgroud)

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

pushd "%CD%"
CD /D "%~dp0"
REM Your commands which require admin privileges here
Run Code Online (Sandbox Code Playgroud)

这不会导致无限循环,也会删除容易出错的管理员权限检查.


Buv*_*inJ 6

另一个 PowerShell 解决方案...

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

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

@powershell "Start-Process -FilePath '%~n0.exe' -WorkingDirectory '%~dp0' -Verb RunAs"
Run Code Online (Sandbox Code Playgroud)

更多信息

Start-Process您还可以申请许多其他选项!查看:https : //docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/start-process?view=powershell-6

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