我希望我的批处理文件只运行提升。如果没有提升,为用户提供一个选项,以提升的方式重新启动批处理。

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

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


当前回答

如果不是,我使用PowerShell重新启动提升的脚本。把这些句子放在你剧本的最上面。

net file 1>nul 2>nul && goto :run || powershell -ex unrestricted -Command "Start-Process -Verb RunAs -FilePath '%comspec%' -ArgumentList '/c %~fnx0 %*'"
goto :eof
:run
:: TODO: Put code here that needs elevation

我从@Matt的答案中复制了“net name”方法。他的回答有更好的文档记录,并有错误消息等。这个版本的优势在于PowerShell已经在Windows 7及以上版本上安装并可用。没有临时VBScript (*.vbs)文件,也不需要下载工具。

只要您的PowerShell执行权限没有被锁定,这个方法应该不需要任何配置或设置就可以工作。

其他回答

我是这样做的:

NET SESSION
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
(Do whatever you need to do here)
EXIT

这样做很简单,只使用windows默认命令。 如果你需要重新分发你的批处理文件,这是很好的。

CD /d %~dp0将当前目录设置为文件的当前目录(如果还不是,则与文件所在的驱动器无关,这要归功于/d选项)。

返回当前带扩展名的文件名(如果你不包含扩展名,并且文件夹中有一个同名的exe,它将调用exe)。

这个帖子有这么多回复,我甚至不知道我的回复是否会被看到。

无论如何,我发现这种方法比其他答案上提出的其他解决方案更简单,我希望它能帮助到一些人。

使用powershell。

如果cmd文件很长,我使用第一个需要提升,然后调用一个做实际工作。

如果脚本是一个简单的命令,那么所有内容都可以放在一个cmd文件中。不要忘记在脚本文件中包含路径。

模板:

@echo off
powershell -Command "Start-Process 'cmd' -Verb RunAs -ArgumentList '/c " comands or another script.cmd go here "'"

示例1:

@echo off
powershell -Command "Start-Process 'cmd' -Verb RunAs -ArgumentList '/c "powershell.exe -NoProfile -ExecutionPolicy Bypass -File C:\BIN\x.ps1"'"

示例2:

@echo off
powershell -Command "Start-Process 'cmd' -Verb RunAs -ArgumentList '/c "c:\bin\myScript.cmd"'"

Matt给出了一个很好的答案,但它去掉了传递给脚本的任何参数。下面是我对参数的修改。我还在Windows 8中加入了Stephen对工作目录问题的修复。

@ECHO OFF
setlocal EnableDelayedExpansion

::net file to test privileges, 1>NUL redirects output, 2>NUL redirects errors
NET FILE 1>NUL 2>NUL
if '%errorlevel%' == '0' ( goto START ) else ( goto getPrivileges ) 

:getPrivileges
if '%1'=='ELEV' ( goto START )

set "batchPath=%~f0"
set "batchArgs=ELEV"

::Add quotes to the batch path, if needed
set "script=%0"
set script=%script:"=%
IF '%0'=='!script!' ( GOTO PathQuotesDone )
    set "batchPath=""%batchPath%"""
:PathQuotesDone

::Add quotes to the arguments, if needed.
:ArgLoop
IF '%1'=='' ( GOTO EndArgLoop ) else ( GOTO AddArg )
    :AddArg
    set "arg=%1"
    set arg=%arg:"=%
    IF '%1'=='!arg!' ( GOTO NoQuotes )
        set "batchArgs=%batchArgs% "%1""
        GOTO QuotesDone
        :NoQuotes
        set "batchArgs=%batchArgs% %1"
    :QuotesDone
    shift
    GOTO ArgLoop
:EndArgLoop

::Create and run the vb script to elevate the batch file
ECHO Set UAC = CreateObject^("Shell.Application"^) > "%temp%\OEgetPrivileges.vbs"
ECHO UAC.ShellExecute "cmd", "/c ""!batchPath! !batchArgs!""", "", "runas", 1 >> "%temp%\OEgetPrivileges.vbs"
"%temp%\OEgetPrivileges.vbs" 
exit /B

:START
::Remove the elevation tag and set the correct working directory
IF '%1'=='ELEV' ( shift /1 )
cd /d %~dp0

::Do your adminy thing here...

您可以使用psexec的-h选项让脚本调用自身以提升运行。

我不确定你如何检测到它是否已经处于升高状态……也许只有在出现“访问被拒绝”错误时才会重新尝试提升烫发?

或者,你可以简单地让xcopy和reg.exe命令总是使用psexec -h运行,但是如果最终用户每次都需要输入密码(或者如果你在脚本中包含密码则不安全),这对他们来说会很烦人……

我最近需要一个用户友好的方法,我根据这里和其他地方的贡献者的宝贵见解想出了这个方法。只需将这一行放在.bat脚本的顶部。欢迎您的反馈。

@pushd %~dp0 & fltmc | find "." && (powershell start '%~f0' ' %*' -verb runas 2>nul && exit /b)

无畏:

@pushd %~dp0 ensures a consistant working directory relative to this batch file; supports UNC paths fltmc a native windows command that outputs an error if run unelevated | find "." makes the error prettier, and causes nothing to output when elevated && ( if we successfully got an error because we're not elevated, do this... powershell start invoke PowerShell and call the Start-Process cmdlet (start is an alias) '%~f0' pass in the full path and name of this .bat file. Single quotes allow spaces in the path/file name ' %*' pass in any and all arguments to this .bat file. Funky quoting and escape sequences probably won't work, but simple quoted strings should. The leading space is needed to prevent breaking things if no arguments are present -verb runas don't just start this process...RunAs Administrator! 2>nul discard PowerShell's unsightly error output if the UAC prompt is canceled/ignored. && if we successfully invoked ourself with PowerShell, then... NOTE: in the event we don't obtain elevation (user cancels UAC), then && allows the .bat to continue running without elevation, such that any commands that require it will fail but others will work just fine. If you want the script to simply exit instead of running unelevated, make this a single ampersand: & exit /b) exits the initial .bat processing, because we don't need it anymore; we have a new elevated process currently running our .bat. Adding /b allows cmd.exe to remain open if the .bat was started from the command line...it has no effect if the .bat was double-clicked