如何自动提升我的批处理文件,以便它在需要时向 UAC 管理员权限请求?

2023-11-20

我希望我的批处理文件仅运行提升。如果未提升,请为用户提供一个选项,以在提升后重新启动批处理。

我正在编写一个批处理文件来设置系统变量,将两个文件复制到程序文件位置,然后启动驱动程序安装程序。如果 Windows 7/Windows Vista 用户 (UAC启用,即使他们是本地管理员)运行它而不右键单击并选择“以管理员身份运行”,他们将“访问被拒绝”复制两个文件并写入系统变量。

如果用户实际上是管理员,我想使用命令自动重新启动批处理。否则,如果他们不是管理员,我想告诉他们他们需要管理员权限才能运行批处理文件。我在用着xcopy复制文件并REG ADD写入系统变量。我正在使用这些命令来处理可能的 Windows XP 计算机。我在这个主题上发现了类似的问题,但没有任何涉及重新启动批处理文件的问题。


有一种简单的方法,无需使用外部工具 - 它运行良好Windows 7、8、8.1、10 和 11并且也向后兼容(Windows XP 没有任何 UAC,因此不需要提升 - 在这种情况下,脚本将继续执行)。

Check out this code (I was inspired by the code by NIronwolf posted in the thread Batch File - "Access Denied" On Windows 7? 1), but I've improved it - in my version there isn't any directory created and removed to check for administrator privileges):

::::::::::::::::::::::::::::::::::::::::::::
:: Elevate.cmd - Version 4
:: Automatically check & get admin rights
:: see "https://stackoverflow.com/a/12264592/1016343" for description
::::::::::::::::::::::::::::::::::::::::::::
 @echo off
 CLS
 ECHO.
 ECHO =============================
 ECHO Running Admin shell
 ECHO =============================

:init
 setlocal DisableDelayedExpansion
 set cmdInvoke=1
 set winSysFolder=System32
 set "batchPath=%~dpnx0"
 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
  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 & 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

该脚本利用了以下事实:NET FILE需要管理员权限并返回errorlevel 1如果你没有它。提升是通过创建一个重新启动批处理文件以获取权限的脚本来实现的。这会导致 Windows 显示 UAC 对话框并要求您输入管理员帐户和密码。

我已经在 Windows 7、8、8.1、10、11 和 Windows XP 上对其进行了测试 - 它对所有系统都适用。 优点是,在启动点之后,您可以放置​​任何需要系统管理员权限的内容,例如,如果您打算重新安装并重新运行 Windows 服务以进行调试(假设 mypackage.msi 是服务安装程序包) :

msiexec /passive /x mypackage.msi
msiexec /passive /i mypackage.msi
net start myservice

如果没有此权限提升脚本,UAC 会询问您三次管理员用户名和密码 - 现在只在开始时询问一次,并且仅在需要时询问。


如果您的脚本只需要显示错误消息并在没有任何管理员权限的情况下退出代替自动提升,这甚至更简单:您可以通过在脚本开头添加以下内容来实现此目的:

@ECHO OFF & CLS & ECHO.
NET FILE 1>NUL 2>NUL & IF ERRORLEVEL 1 (ECHO You must right-click and select &
  ECHO "RUN AS ADMINISTRATOR"  to run this batch. Exiting... & ECHO. &
  PAUSE & EXIT /D)
REM ... proceed here with admin rights ...

这样,用户必须右键单击并选择“以管理员身份运行”。该脚本将在REM如果检测到管理员权限则声明,否则退出并出错。如果您不需要PAUSE,只需将其删除即可。重要的: NET FILE [...] EXIT /D)必须在同一条线上。为了更好的可读性,它在这里以多行显示!


在某些机器上,我遇到了问题,这些问题已经在上面的新版本中解决了。一个是由于不同的双引号处理,另一个问题是由于 Windows 7 计算机上的 UAC 被禁用(设置为最低级别),因此脚本一次又一次地调用自身。

我现在已经通过删除路径中的引号并稍后重新添加它们来解决此问题,并且我添加了一个额外的参数,该参数是在脚本以提升的权限重新启动时添加的。

双引号被以下删除(详细信息是here):

setlocal DisableDelayedExpansion
set "batchPath=%~0"
setlocal EnableDelayedExpansion

然后您可以使用以下方式访问该路径!batchPath!。它不包含任何双引号,所以可以肯定地说"!batchPath!"稍后在脚本中。

The line

if '%1'=='ELEV' (shift & goto gotPrivileges)

检查脚本是否已被调用VBScript脚本来提升权限,从而避免无休止的递归。它使用删除参数shift.


Update:

  • 为了避免必须注册.vbs延伸于Windows 10,我已经更换了线
    "%temp%\OEgetPrivileges.vbs"
    by
    "%SystemRoot%\System32\WScript.exe" "%temp%\OEgetPrivileges.vbs"
    在上面的脚本中;还添加了cd /d %~dp0按照 Stephen(单独答案)和 Tomáš Zato(评论)的建议,将脚本目录设置为默认值。

  • 现在,该脚本支持传递给它的命令行参数。感谢 jxmallet、TanisDLJ 和 Peter Mortensen 的观察和启发。

  • 根据Artjom B.的提示,我分析了它并替换了SHIFT by SHIFT /1,它保留了文件名%0范围

  • Added del "%temp%\OEgetPrivileges_%batchName%.vbs" to the :gotPrivileges要清理的部分(如mlt建议)。添加%batchName%以避免并行运行不同批次时产生影响。请注意,您需要使用for能够利用高级字符串函数,例如%%~nk,它仅提取文件名。

  • 优化脚本结构,改进(添加变量vbsGetPrivileges现在到处都可以引用它,可以轻松更改文件的路径或名称,只需删除.vbs文件(如果需要提升批次)

  • 在某些情况下,提升需要不同的调用语法。如果脚本不起作用,请检查以下参数:
    set cmdInvoke=0
    set winSysFolder=System32
    将第一个参数更改为set cmdInvoke=1并检查是否已经解决了问题。它将添加cmd.exe到执行提升的脚本。
    或者尝试将第二个参数更改为winSysFolder=Sysnative,这可能对 64 位系统有帮助(但在大多数情况下不是必需的)。 (ADBailey 已对此进行了报道)。仅当从 32 位脚本主机启动 64 位应用程序时才需要“Sysnative”(例如 Visual Studio 构建过程或从另一个 32 位应用程序调用脚本)。

  • 为了更清楚如何解释参数,我现在将其显示为P1=value1 P2=value2 ... P9=value9。如果您需要将路径等参数括在双引号中,例如"C:\Program Files".

  • 如果要调试VBS脚本,可以添加//X按照建议,将 WScript.exe 参数作为第一个参数here(它是针对 CScript.exe 进行描述的,但也适用于 WScript.exe)。

  • 错误修正由提供米格尔·安吉洛:batchPath 现在可以在 cmd shell 上正确返回。这个小脚本test.cmd显示了差异,对于那些对细节感兴趣的人(在 cmd.exe 中运行它,然后通过 Windows 资源管理器双击运行它):

    @echo off
    setlocal
    set a="%~0"
    set b="%~dpnx0"
    if %a% EQU %b% echo running shell execute
    if not %a% EQU %b% echo running cmd shell
    echo a=%a%, b=%b% 
    pause
    

有用的链接:

  • 批处理文件中特殊字符的含义:
    引号 (”), Bang (!), 插入符号 (^), , 其他特殊字符

1) Note that this link no longer exists, it is now showing a 404 error.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何自动提升我的批处理文件,以便它在需要时向 UAC 管理员权限请求? 的相关文章

  • 自定义波特率,redux

    我遇到的问题详述如下自定义波特率 https stackoverflow com questions 7714060 custom baud rate SetCommState 波特率 921600 失败 但波特率 115200 成功 尽管
  • 在 Windows 上不使用 OpenSSL 从 pfx 文件或证书存储中提取私钥

    正如标题所示 我想在不使用 OpenSSL 或任何其他第三方工具的情况下导出我的私钥 如果我需要一个 cer文件或 pfx我可以通过 MMC 或 PowerShell 轻松导出这些文件pkiclient但我找不到获取私钥的方法 https
  • 如何将 GIT 调用的输出获取到批处理脚本中的变量中?

    我有一个 git 命令来获取当前存储库的最新 SHA 如下所示 git log pretty format H n 1 我有一个 Windows 批处理脚本 我想按如下方式使用它 SET CURRENT SHA 但我不知道如何将从 git
  • 如何在批处理文件中回显换行符?

    如何从批处理文件输出中插入换行符 我想做类似的事情 echo hello nworld 这会输出 hello world Use echo hello echo echo world
  • 更改 Wi-Fi 配置文件的密码

    在我志愿服务的长期护理医院中 每个月的第一天 访客 Wi Fi 连接的密码都会更改 这给工作人员带来了大量的工作 也给患者带来了很多挫败感 其中许多人的行动能力非常有限 是的 真正的解决方案是让 IT 团队保留相同的密码 但这不会发生 大多
  • Windows 窗口对接

    我想知道如何在 Windows 中将窗口停靠 捕捉到屏幕的一侧 最好使用直接的 Win32 API 我正在寻找的效果就像任务栏 一个在屏幕上有保留空间的窗口 因此最大化另一个窗口会使该窗口占据屏幕的其余部分 但使我的窗口保持在适当的位置并可
  • 不在焦点时响应键盘? (C#、Vista)

    我正在尝试编写一个应用程序 只要按下 Shift 键 无论当前哪个应用程序具有焦点 它都会做出响应 我尝试过这个SetWindowsHookEx 与GetKeyboardState 但这两种方法仅在应用程序窗口具有焦点时才有效 我需要它在全
  • 如何查看网络连接状态是否发生变化?

    我正在编写一个应用程序 用于检查计算机是否连接到某个特定网络 并为我们的用户带来一些魔力 该应用程序将在后台运行并执行检查是否用户请求 托盘中的菜单 我还希望应用程序能够自动检查用户是否从有线更改为无线 或者断开连接并连接到新网络 并执行魔
  • 非托管 C++ 中的默认打印机

    我正在寻找一种使用非托管 C 查找 Windows 默认打印机名称的方法 找到了大量 NET 示例 但非托管没有成功 谢谢 以下是如何获取当前打印机和默认打印机的列表 如果有一台设置为默认打印机 另请注意 如果用户没有打印机或未将打印机名称
  • 备份并上传到FTP服务器[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 谁能指导我一个脚本解决方案来备份目录并将其上传到 ftp 服务器 我最初正在寻找批处理脚本 但任何解决
  • 使用批处理文件创建 exe 的快捷方式

    我知道这样的主题已经存在 但我不想使用 VB 脚本 我希望你能在 DOS 中使用命令行创建快捷方式 请发布一些很棒的例子 Thanks AA 如果不调用外部程序 则无法在 bat 文件中创建快捷方式 然而 自 Win2k 以来的每个版本的
  • 当我启动 Windows 命令提示符时,我做了什么导致环境变量发生更改?

    我使用的是 Windows 10 x64 我安装了 Anaconda3 如果我启动 C Windows system32 cmd exe 时没有运行任何其他内容 并且在我可以看到的后台中没有任何有趣的内容 则以下内容将添加到控制面板 UI
  • 将所有文件与指定目录(和子目录)中的所有文件进行二进制比较

    我需要将目录及其子目录中包含的所有文件与同一目录及其子目录中包含的所有其他文件进行比较 并将匹配文件的路径记录到文本文件或 CSV 我意识到有一些软件工具可以做到这一点 但除非它可以在 Windows 中开箱即用 否则我将不被允许在我的网络
  • 批处理文件 FOR/f 扩展

    我有一个文件 directories txt 与目录名称 每个在一行上 我喜欢扩展该行 C Documents and Settings USERNAME My Documents 在我的脚本中以真实用户名运行脚本 然而 回声与线路完全相同
  • 通过批处理文件自动化 cygwin

    长话短说 我们有多个服务器 我们每晚都在其上运行 perflog 监控 我的工作是将这些日志转换为 csv 格式并将它们发送到我的电子邮件 这一点已经通过前员工编写的 sh 脚本实现了自动化 我想要自动化的是在 perfmon 日志记录之后
  • 供所有 Win32 程序员在 Windows Aero Glass(DWM、GDI、GDI+)上绘图的文档和 API 示例

    我正在寻找良好的资源来学习使用 Win32 GDI API 或任何替代它的内容 以便使用 Win32 API 直接在玻璃窗体上进行绘制和绘制 当我使用 Delphi 时 我将其标记为 Delphi 或 Visual C 您能找到的任何代码示
  • 为什么 Git Bash 无法运行我的可执行文件?

    I am on git for windows https github com git for windows 吉特 巴什 我无法在命令行上运行可执行文件 Pedr Abc 07 MINGW64 c dev ls sqlite3 exe
  • 使用Windows 7计算器进行对数计算[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我想使用Windows计算器在科学模式中为了求解一个非常基本的对数方程 但不幸的是 我无法做到这一点 问题是这样的 log 5 125 非常感谢您的帮
  • 使用node.js安装xml2json时出错

    我尝试为 node js 安装 xml2json 包 但它给了我错误 Error are as below 我的系统配置如下 Node js 版本 v5 4 1 npm 版本 3 3 12 操作系统 Windows 10 64 位 pyth
  • 从 Powershell 脚本安装 Python

    当以管理员身份从 PowerShell 命令行运行以下命令时 可以在 Windows 11 上成功安装 Python c temp python 3 11 4 amd64 exe quiet InstallAllUsers 0 Instal

随机推荐

  • 找不到强大的模块 - Node.js

    我开始使用 node j 进行开发 我遇到了有关使用 formidable 模块的问题 我有这个错误 错误 找不到模块 强大 以下是使用 npm lsinstalled 安装的模块列表 email protected email prote
  • 从命令行进行 MySQL 备份和恢复

    我正在使用命令行来备份和恢复 MYSQL 数据库 让我们使用我有一个数据库 Data1 其中包含视图和过程 当在Cmd line I use mysqldump i e gt bin gt mysqldump u root proot Da
  • CSS“content”属性中的 HTML 特殊字符

    我正在尝试使用 CSS before content 字段在项目之前添加内容 我想插入一个复选标记 但如果我在内容选项中使用它 它会打印为文字 我如何告诉 CSS 使其成为复选标记 而不是文字字符串 尝试这个 target before c
  • 如果用户 = 系统,.NET 用户设置存储在哪里?

    我一直在使用更新来更新我的一个应用程序并使用Properties Settings Default Upgrade 并发现我的更新程序重新启动我的应用程序后 它在系统用户而不是默认 登录用户下运行 这让我想知道 SYSTEM 的 user
  • 如何在 Perl 中使用变量作为正则表达式修饰符?

    我正在编写一个抽象函数 它将询问用户一个给定的问题并根据给定的正则表达式验证答案 重复该问题 直到答案与验证正则表达式匹配 但是 我还希望客户端能够指定答案是否必须区分大小写 所以像这样 sub ask my prompt validati
  • 如何检查 CachedRowSet 中是否存在列名?

    我正在从可能发生变化的视图中查询数据 在执行操作之前我需要知道该列是否存在crs get 我发现我可以查询metadata像这样在我请求数据之前查看一列是否存在 ResultSetMetaData meta crs getMetaData
  • 使用预定义的自定义键顺序数组按键对数组进行排序

    a array 0 gt a 1 gt b 2 gt c 3 gt d 我想将顺序更改为3 2 0 1 a array 3 gt d 2 gt c 0 gt a 1 gt b 如果您想以编程方式更改顺序 请查看各种PHP 中的数组排序函数
  • C# XNA 鼠标位置

    我在 XNA 中的鼠标坐标遇到一些问题 0x0 任意靠近 但不在 屏幕的左上角 我现在正在窗口模式下运行游戏 但坐标是基于屏幕的 而不是游戏窗口的 尽管 XNA 文档告诉我应该是其他情况 提前致谢 这是代码 namespace TheGam
  • MATLAB 编辑器中可以进行多光标编辑吗?

    Is there a way to multiline edit code in matlab Instead of copy paste a single line repeatedly or copy paste from matlab
  • 用连字符分隔的大小写的名称是什么?

    这是帕斯卡命名法 SomeSymbol 这是驼峰式命名法 someSymbol 这是snake case some symbol 所以我的问题是是否有一个被广泛接受的名称 some symbol 它通常用于 url 中 这个案例约定并没有真
  • C++ 时间戳到人类可读的日期时间函数

    我有一个简单的函数 我需要从时间戳返回人类可读的日期时间 但不知何故 它以秒为单位返回相同的时间戳 输入1356953890 std string UT timeStampToHReadble long timestamp const ti
  • 如何验证sqlplus可以连接?

    我想知道是否有可能获得sqlplus以某种方式输出以发现我的数据库是否已启动 我想在数据库上运行脚本列表 但在执行此操作之前 我想知道数据库是否已启动并正在使用我的脚本运行 这是我尝试过的 sqlplus DB1 lt lt EOF gt
  • 如何仅当querytext的长度等于2时才开始过滤

    如何才能仅当查询文本的长度等于 2 时才开始过滤 我有这段代码 但我不知道如何仅在 querytext length gt 2 时开始过滤
  • 关于 C 系列语言中有符号整数的使用

    当在我自己的代码中使用整数值时 我总是尝试考虑符号性 问自己整数是否应该有符号或无符号 当我确定该值永远不需要为负数时 我会使用无符号整数 我不得不说这种情况大多数时候都会发生 在阅读其他人的代码时 我很少看到无符号整数 即使表示的值不能为
  • 事件源与原始源

    我正在阅读 C WPF 书 在路由事件章节中 事件有 2 个相同的属性Source and OriginalSource 我没有看到它们之间的区别 Xaml
  • JasperReports:如何在两列中显示数据

    这是我当前的 jrxml 文件
  • Spark 流中找不到 KafkaUtils 类

    我刚刚开始使用 Spark Streaming 正在尝试构建一个示例应用程序来计算 Kafka 流中的单词数 虽然它编译的是sbt package 当我运行它时 我得到NoClassDefFoundError This post似乎有同样的
  • iPhone中使用NSData的内存泄漏问题

    内存泄漏问题 NSConcreteData to set tip photo in photo frame NSData data NSData dataWithContentsOfURL NSURL URLWithString pathO
  • 当 scipy.optimize.minimize 可能用于相同的事情时,为什么 scipy.optimize.least_squares 存在?

    我试图理解为什么scipy optimize least squares存在于scipy 该函数可用于执行模型拟合 然而 人们可以使用scipy optimize minimize做同样的事情 唯一的区别是scipy optimize le
  • 如何自动提升我的批处理文件,以便它在需要时向 UAC 管理员权限请求?

    我希望我的批处理文件仅运行提升 如果未提升 请为用户提供一个选项 以在提升后重新启动批处理 我正在编写一个批处理文件来设置系统变量 将两个文件复制到程序文件位置 然后启动驱动程序安装程序 如果 Windows 7 Windows Vista