Powershell 删除引号参数

Powershell Removing Quotes Argument

我正在使用 Start-Process 以管理员身份启动另一个 Powershell 实例,但是当我尝试传递参数列表时,无论是作为变量还是纯字符串,Powershell 都会删除引号。下面是我正在使用的命令:

$argu = '-noexit "C:\Program Files (x86)\Microsoft Visual Studio17\BuildTools\VC\Auxiliary\Build\vcvars64.bat"';
powershell Start-Process -Verb RunAs -FilePath powershell -ArgumentList $argu

这是我得到的错误:

x86 : The term 'x86' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included,
verify that the path is correct and try again.
At line:1 char:88
+ ... Program Files (x86)\Microsoft Visual Studio17\BuildTools\VC\Auxiliary\Build\v ...
+                    ~~~
    + CategoryInfo          : ObjectNotFound: (x86:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

提前感谢您的帮助。

更新:

$argu = '''-noexit ""C:\Program Files (x86)\Microsoft Visual Studio17\BuildTools\VC\Auxiliary\Build\vcvars64.bat""''';
powershell Start-Process -Verb RunAs -FilePath powershell -ArgumentList $argu

这几乎修复了它,但现在我在 第二个 window 而不是第一个

中得到了上面的错误。

(A) 来自内部 PowerShell:

$argu = '-noexit -command & \"C:\Program Files (x86)\Microsoft Visual Studio17\BuildTools\VC\Auxiliary\Build\vcvars64.bat\"'
Start-Process -Verb RunAs -FilePath powershell -ArgumentList $argu

注意:我不会通过 powershell.exe 调用 Start-Process,因为通常不需要这样做。

  • 嵌入式 "\ 转义的,这是 PowerShell 在调用其 CLI 时所需要的(也许令人惊讶,假设 PowerShell 内部是 ` 作为转义字符)。

    • 也就是说,鉴于 " 嵌入在 '...' 中,它们不应该需要 extra 转义 - 见下文。
  • 要执行的文件路径以调用运算符 & 为前缀,因为您需要它来执行以引用形式指定的文件。

  • 请注意,我添加了 -Command,这在 Windows PowerShell 中并非绝对必要,但如果您 运行 来自 PowerShell 核心(现在默认为-File)。


或者,您也可以单独指定参数,作为 数组 的一部分,这可以说是更简洁的解决方案:

$argu = '-noexit', '-command', '&', 'de', 
  '\"C:\Program Files (x86)\Microsoft Visual Studio17\BuildTools\VC\Auxiliary\Build\vcvars64.bat\"'
Start-Process -Verb RunAs -FilePath powershell -ArgumentList $argu

可悲的是,即使在这种情况下,您也需要额外的嵌入式引号 用于包含空格的参数,即 a known Start-Process problem being tracked on GitHub.

PowerShell 在调用外部程序时对引用的处理通常是有问题的; this GitHub issue.

中总结了当前的问题

(B) 来自 外部 PowerShell(cmd.exe,自定义文件资源管理器上下文菜单):

powershell -command Start-Process -Verb RunAs -FilePath powershell -ArgumentList '-noexit -command . ''C:\Program Files (x86)\Microsoft Visual Studio17\BuildTools\VC\Auxiliary\Build\vcvars64.bat'''
  • -引号现在被使用(嵌套单引号转义为''),因为双引号会使转义变得非常复杂。

  • .代替&执行.bat文件,避免了&解析的问题;虽然 . 通常与 & 有不同的用途,但在调用 外部 程序时,这两个运算符的行为相同。

  • 如果您还想为最终打开提升权限的 PowerShell 会话设置 工作目录,您需要合并一个明确的 Set-Location ( cd) 调用命令字符串,因为 Start-Process -Verb RunAs 始终默认为 SYSTEM32 文件夹(即使 -WorkingDirectory 参数在这种情况下也无济于事)。

    • 然而,为了安全地工作,您必须使用 double-quoting quote 目录路径,给定文件名可能包含单引号;使用 %V 作为目录路径(文件资源管理器提供给通过自定义上下文菜单调用的命令),正确转义的 Set-Location 调用看起来像这样(我希望我是在开玩笑):

      • Set-Location \"\"\"%V%\"\"\"

集成到完整命令中(为简洁起见,使用 Set-Location 的内置别名 cd):

powershell -command Start-Process -Verb RunAs -FilePath powershell -ArgumentList '-noexit -command cd \"\"\"%V%\"\"\"; . ''C:\Program Files (x86)\Microsoft Visual Studio17\BuildTools\VC\Auxiliary\Build\vcvars64.bat'''

顺便说一句:PowerShell Core 现在有一个 -WorkingDirectory (-wd) CLI 参数,允许您更稳健地控制启动目录 (pwsh -wd "c:\path\to\dir" ...);事实上,prompted the introduction of this parameter.

正是文件资源管理器自定义上下文菜单用例