powershell 向Start-Process传递参数时使用空格

c8ib6hqw  于 2023-01-26  发布在  Shell
关注(0)|答案(2)|浏览(260)

我想把powershell参数传递给一个进程。参数可以包含空格。
Powershell代码:

$proc = Start-Process -FilePath "wsl.exe" -ArgumentList $args -NoNewWindow -PassThru
$proc | Wait-Process

运行命令

powershell -noprofile -executionpolicy bypass -file sh.ps1 bash -c "`"echo Hello World`""

无输出。
使用静态数组运行此命令可以正常工作:

$proc = Start-Process -FilePath "wsl.exe" -ArgumentList @("bash", "-c", "`"echo Hello World`"") -NoNewWindow -PassThru
$proc | Wait-Process

产出

Hello World

我需要做什么来从CLI参数中转义参数?
查看https://github.com/PowerShell/PowerShell/issues/5576为什么必须转义空格

2wnc66cl

2wnc66cl1#

显而易见的答案是这样的,$myargs是一个字符串数组,“echo Hello World”需要在它周围嵌入双引号(或单引号),这会使事情变得复杂。

$myargs = "bash", "-c", "'echo Hello World'"
$proc = Start-Process -FilePath wsl.exe -ArgumentList $myargs -NoNewWindow -PassThru
$proc | Wait-Process

Hello World

我只会说:

.\sh.ps1 bash -c 'echo hello world'

# sh.ps1 contains:
# wsl $args

或者是针对Windows的wsl bash:

bash -c 'echo hello world'

我碰巧在wsl中安装了pwsh,如果没有单引号,每个单词都会被放在新的一行。

wsl pwsh -c "echo 'hello world'"

我在另一个powershell中也可以这样做,但嵌入了另一组引号:

powershell -noprofile -executionpolicy bypass -file sh.ps1 bash -c "`"'echo Hello World'`""
sr4lhrrt

sr4lhrrt2#

在您的情况下,没有充分的理由使用Start-Process(请参阅this GitHub docs issue,以获得关于Start-Process何时适用以及何时不适用的指导)。
相反,使用 direct execution,它不仅是同步的,并且在同一个控制台窗口中运行(对于wsl.exe这样的 console 应用程序),而且还允许您直接捕获或重定向输出。
这样做,您还将 * 绕过 * 您提到的长期存在的Start-Process bug(GitHub issue #5576),因为PowerShell在幕后 * 根据需要 * 将参数传递给外部程序(即如果它们包含空格)。

$exe, $exeArgs = $args   # split argument array into exe and pass-thru args
wsl.exe -e $exe $exeArgs # execute synchronously, via wsl -e

请注意,您也不需要在PowerShell CLI调用中 * 嵌入 * 转义的"

powershell -noprofile -executionpolicy bypass -file sh.ps1 bash -c "echo Hello World"

然而,如果您的参数确实需要嵌入式",您将遇到另一个长期存在的PowerShell错误,该错误仅影响外部程序的 * 直接 * 调用,因此必须使用\进行 * 手动 * 转义-请参见this answer

如果您 * 确实 * 需要使用Start-Process-例如,如果您希望进程在 * 新(控制台)窗口 * 中运行-则必须在需要它的$args元素周围提供 * 嵌入式 * 引号,如下所示:

$quotedArgs = foreach ($arg in $args) {
  if ($arg -notmatch '[ "]') { $arg }
  else { # must double-quote
    '"{0}"' -f ($arg -replace '"', '\"' -replace '\\$', '\\')
  }
}

$proc = Start-Process -FilePath "wsl.exe" -ArgumentList $quotedArgs -PassThru
$proc | Wait-Process

相关问题