自动获取管理员权限的批处理文件

很多时候,执行一些需要管理员权限的批处理文件时我们需要右击,然后选择 使用管理员权限运行 后, 批处理文件才能正确运行,如果我们忘记了提升权限而直接运行,这些批处理文件会因为没有权限而报错, 那么有没有办法让批处理文件自己检查权限,并且在没有权限时提示我们是否赋予权限呢

更新

这个方法在 win10 下已经失效了,我推测的原因应该是 windows 内嵌的防毒机制认为, 使用管理员权限执行一个临时文件是危险行为,不用担心,这里还有一个替代方案

如何自动提升管理员权限

stackoverflow 上关于这个问题有一个很好的讨论,有好几个解决方案,总结下来,基本流程是这样:

  1. 检查当前是否有管理员权限,如果是,跳过 2
  2. 创建一个临时脚本文件或对象提升权限,重新执行批处理文件
  3. 执行实际的批处理操作

选择解决方案

比较了几个答案之后,我认为 这个答案 的做法最为简单干净,有以下几个理由

  • 只依赖 cmd,有些解决方法需要使用 powershell 或其他程序配合
  • 不会创建临时文件,有些解决方法会在临时目录创建一个脚本程序来执行
  • 简短,不过这个简短也是有代价的,比如可能不会支持参数传递, 但是方便我们理解提升权限的必要步骤

确定批处理文件内容

我参考其他答案对原本代码做了一些修改,最终的版本及注释如下:

@ECHO OFF
:: 第一行的作用是取消显示输出
:: 检查权限,不输出结果,也不输出错误
NET SESSION 1>NUL 2>NUL
:: 如果没有权限,跳至提升权限段
IF %ERRORLEVEL% NEQ 0 GOTO ELEVATE
:: 跳至实际需要执行的批处理段
GOTO ADMINTASKS

:: 提升权限段
:ELEVATE
:: 记录当前路径
CD /d %~dp0
:: 使用 javascript 用管理员权限重新执行该批处理文件
MSHTA "javascript: var shell = new ActiveXObject('shell.application'); shell.ShellExecute('%~nx0', '', '', 'runas', 1);close();"
:: 退出
EXIT

:: 实际需要执行的批处理段
:ADMINTASKS
:: 在下面加入需要管理员权限的定制内容

正常使用时我们可以去掉注释

@ECHO OFF
NET SESSION 1>NUL 2>NUL
IF %ERRORLEVEL% NEQ 0 GOTO ELEVATE
GOTO ADMINTASKS

:ELEVATE
CD /d %~dp0
MSHTA "javascript: var shell = new ActiveXObject('shell.application'); shell.ShellExecute('%~nx0', '', '', 'runas', 1);close();"
EXIT

:ADMINTASKS

测试

  1. 我们在桌面上创建一个 test.cmd 内容如下

    @ECHO OFF
    NET SESSION 1>NUL 2>NUL
    IF %ERRORLEVEL% NEQ 0 GOTO ELEVATE
    GOTO ADMINTASKS
    
    :ELEVATE
    CD /d %~dp0
    MSHTA "javascript: var shell = new ActiveXObject('shell.application'); shell.ShellExecute('%~nx0', '', '', 'runas', 1);close();"
    EXIT
    
    :ADMINTASKS
    net user
    pause
  2. 双击文件执行后,我们就会看到提示是否用管理员权限执行的 uac 窗口了,这里我们选择 https://i.loli.net/2018/05/25/5b0769b1eca8f.png
  3. 接下来批处理就会执行到实际需要执行的批处理段,我们测试的批处理是显示主机上的用户,然后暂停 https://i.loli.net/2018/05/25/5b076affcc985.png

总结

终于我们可以忘记右键选择管理员运行批处理文件了,只是要做一点小小的改造……