将引用的参数从批处理文件传递给`powershell start` - 按需自我提升

问题描述 投票:3回答:3

我正在编写一个Windows批处理文件,如果用户在出现的“用户访问控制”对话框中单击“是”,则会自动将其自身升级为管理权限。

我正在使用一种技术,我学习here来检测我们是否已经拥有管理员权限,另一种来自here以升级。在适当的时候,下面的脚本,我们称之为foo.bat,通过对PowerShellspopo的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中(其中第二个参数应该是两个单词,“two three”)。

当我用静态参数替换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',我尝试过引用,插入符号,加倍和三倍引号,反引号和逗号的各种荒谬组合,但是批处理文件引用和PowerShell引用之间存在一些不正常的交互,并且没有任何效果。

这甚至可能吗?

powershell batch-file escaping quotes elevated-privileges
3个回答
3
投票
  • 你已经遇到了两个引用地狱(the docs for powershell's Start-Process和PowerShell)的完美风暴,装饰着cmd(从PowerShell Core 6.2.0开始)。
  • 要解决该错误,批处理文件不能直接重新调用,而必须通过PowerShell bug重新调用。
  • 考虑到这一点的cmd /c通常有效,但在以下边缘情况下则不然: 如果批处理文件的完整路径包含空格(例如,LotPings' helpful answer) 如果参数碰巧包含以下任何c:\path\to\my batch file.cmd元字符(甚至在cmd内):"...";例如,& | < > ^ 如果reinvoked-with-admin-privileges批处理文件依赖于在最初调用它的同一工作目录中执行。

以下解决方案解决了所有这些边缘情况。虽然它远非微不足道,但它应该可以原样重用:

one "two & three"

2
投票

这是我的批次:

@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

样本输出:

::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
投票

唯一获得批准的方法是使用清单。这模拟了Unix的SUDO.EXE。

运行命令并保持高架

-ArgumentList '/k %~f0 %Args:"=\""%

提升当前cmd窗口或创建新的提升窗口

RunAsAdminconsole <Command to run>

来自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>
© www.soinside.com 2019 - 2024. All rights reserved.