我正在编写一个Windows批处理文件,只要用户在出现的“用户访问控制”对话框中单击“是”,它就会自动升级为管理权限。
我正在使用一种我学到的here技术来检测我们是否已经拥有管理员权限,以及从here中获得另一种权限来升级。在适当的情况下,以下脚本(称为foo.bat
)通过Powershell介导的对runas
的调用重新启动:
@echo off
net session >NUL 2>NUL
if %ERRORLEVEL% NEQ 0 (
powershell start -wait -verb runas "%~dpfx0" -ArgumentList '%*'
goto :eof
)
echo Now we are running with admin rights
echo First argument is "%~1"
echo Second argument is "%~2"
pause
我的问题是在-ArgumentList
中转义了引号。如果我从命令提示符处调用foo.bat one two
,但如果其中一个参数包含空格,例如在foo.bat one "two three"
中(例如,第二个参数应为两个单词,“两个三个”。
如果我什至可以用静态参数替换%*
时得到正确的行为:
powershell start -wait -verb runas "%~dpfx0" -ArgumentList 'one "two three"'
然后,我可以在foo.bat
中添加一些行,这些行构成了%*
的适当转义字符。但是,即使在该静态示例中,到目前为止,我尝试过的每个转义模式都失败了(我看到的是Second argument is "two"
而不是Second argument is "two three"
)或导致了错误(通常为Start-Process: A positional parameter cannot be found that accepts argument 'two'
)。借助the docs for powershell's Start-Process,我尝试了各种形式的引号,脱字符,双引号和三引号,反引号和逗号的荒谬组合,但是批处理文件引号和powershell引号之间进行了一些不愉快的交互,但没有任何效果
这有可能吗?
答案 0 :(得分:2)
这是我为此目的的批次:
{"ip_address":"x,y"}
示例输出:
::ElevateMe.cmd::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
@echo off & setlocal EnableExtensions DisableDelayedExpansion
Set "Args=%*"
net file 1>nul 2>&1 || (powershell -ex unrestricted -Command ^
Start-Process -Verb RunAs -FilePath '%comspec%' -ArgumentList '/c %~f0 %Args:"=\""%'
goto :eof)
:: Put code here that needs elevation
Echo:%*
Echo:%1
Echo:%2
Pause
如果您希望升高的cmd保持打开状态,请使用one "two three"
one
"two three"
Drücken Sie eine beliebige Taste . . .
答案 1 :(得分:2)
您遇到了一次完美的风暴,用两个{em> 引用地狱(cmd
和 PowerShell),上面装饰着一个PowerShell bug (从PowerShell Core 6.2.0开始)。
要解决该错误,不能直接 重新调用该批处理文件,而必须通过cmd /c
重新调用该批处理文件。
LotPings' helpful answer,考虑到这一点,通常有效,但在以下情况下不:
c:\path\to\my batch file.cmd
)cmd
个元字符(甚至在"..."
内部):& | < > ^
;例如one "two & three"
以下解决方案解决了所有这些极端情况。虽然它并非无关紧要,但它应该可以重复使用:
@echo off
setlocal
:: Test whether this invocation is elevated (`net session` only works with elevation).
:: If already running elevated (as admin), continue below.
net session >NUL 2>NUL && goto :elevated
:: If not, reinvoke with elevation.
set args=%*
if defined args set args=%args:^=^^%
if defined args set args=%args:<=^<%
if defined args set args=%args:>=^>%
if defined args set args=%args:&=^&%
if defined args set args=%args:|=^|%
if defined args set "args=%args:"=\"\"%"
powershell -NoProfile -ExecutionPolicy Bypass -Command ^
" Start-Process -Wait -Verb RunAs -FilePath cmd -ArgumentList \"/c \"\" cd /d \"\"%CD%\"\" ^&^& \"\"%~f0\"\" %args% \"\" \" "
exit /b
:elevated
:: =====================================================
:: Now we are running elevated, in the same working dir., with args passed through.
:: YOUR CODE GOES HERE.
echo First argument is "%~1"
echo Second argument is "%~2"
pause
答案 2 :(得分:-1)
批准的唯一提升方式是使用清单。这模拟Unix的 SUDO.EXE 。
要运行命令并保持高位状态
RunAsAdminconsole <Command to run>
要提升当前的cmd窗口或创建一个新的提升的窗口
RunAsAdminconsole
来自https://pastebin.com/KYUgEKQv
REM Three files follow
REM RunAsAdminConsole.bat
REM This file compiles RunAsAdminconsole.vb to RunAsAdminconsole.exe using the system VB.NET compiler.
REM Runs a command elevated using a manifest
C:\Windows\Microsoft.NET\Framework\v4.0.30319\vbc "%~dp0\RunAsAdminconsole.vb" /win32manifest:"%~dp0\RunAsAdmin.manifest" /out:"%~dp0\RunAsAdminConsole.exe" /target:exe
REM To use
rem RunAsAdminconsole <Command to run>
pause
RunAsAdmin.manifest
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="*"
name="Color Management"
type="win32"
/>
<description>Serenity's Editor</description>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
'RunAsAdminConsole.vb
'Change cmd /k to cmd /c to elevate and run command then exit elevation
imports System.Runtime.InteropServices
Public Module MyApplication
Public Sub Main ()
Dim wshshell as object
WshShell = CreateObject("WScript.Shell")
Shell("cmd /k " & Command())
End Sub
End Module
----------------------------------------