我正在编写一个 Windows 批处理文件,它会自动将自身升级为管理权限,前提是用户在出现的用户访问控制对话框上单击"is"。
我正在使用我学到的技术 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 引用之间存在一些邪恶的交互,但没有任何效果。这甚至可能吗?
最佳答案
cmd
和 PowerShell)的完美 Storm ,并以 PowerShell bug 装饰。 (从 PowerShell Core 6.2.0 开始)。 cmd /c
重新调用。 . 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
关于powershell - 将带引号的参数从批处理文件传递给 `powershell start` - 按需 self 提升,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54658352/