在 powershell 中生成 notepad++ 当要打开的文件中有空格时

pic*_*ico 2 powershell


$npp = "C:\Program Files\Notepad++\notepad++.exe";

$myfiles = @(
    "C:\bad boys\file1.txt",
    "C:\bad boys\file2.txt",
    "C:\bad boys\file3.txt"
)

foreach ($file in $myfiles) {
    Start-Process -FilePath $npp -ArgumentList "$file" -PassThru  -NoNewWindow | out-null
}
Run Code Online (Sandbox Code Playgroud)

这几乎有效...除了,它不会在记事本++中打开,因为它看到文件名中的空格并认为这是文件路径结束的地方...因此,我无法打开我的文件列表。有什么想法如何解决吗?相反,我得到的是 notepad++ 多次询问我是否要创建文件“C:\bad”

mkl*_*nt0 5

太长了;博士

虽然Joel Coehoorn 的有用答案为您的问题提供了有效的解决方案Start-Process(源于下面详细介绍的错误),但您可以将代码简化为:

foreach ($file in $myfiles) {
  # Note: | Out-Null is a trick that makes calling *GUI* applications
  #       *synchronous* (makes PowerShell wait for them to exit).
  & $npp $file | Out-Null
}
Run Code Online (Sandbox Code Playgroud)

您看到一个长期存在的错误,Start-Process导致它在形成单个字符串编码传递给后面的目标可执行文件的所有参数时,盲目地用空格连接-ArgumentList( -Args) 参数,而不使用带空格的参数所需的嵌入式双引号。场景。

  • 请参阅GitHub 问题 #5576,其中还讨论了修复需要新参数,以免破坏向后兼容性。

因此,必须手动执行所需的嵌入双引号,如 Joel 的回答所示。

当传递多个参数时,最终更容易将单个字符串传递给
-ArgumentList,并根据需要嵌入双引号
- 本质上是通过类似于从 传递多个参数的方式来制定字符串cmd.exe

例如,如果您要一次将两个带空格的文件路径传递给 Notepad++,您将执行以下操作:

Start-Process -Wait -FilePath $npp -ArgumentList "`"C:\bad boys\file1.txt`" `"C:\bad boys\file2.txt`""
Run Code Online (Sandbox Code Playgroud)

或者,由于您的参数字符串不需要字符串插值,因此您可以使用逐字(单引号)字符串来代替,这避免了将嵌入的转义"`"

Start-Process -Wait -FilePath $npp -ArgumentList '"C:\bad boys\file1.txt" "C:\bad boys\file2.txt"'
Run Code Online (Sandbox Code Playgroud)

使用此处字符串是另一个选项,可以避免转义,并且还可以使调用更具可读性(也适用于单引号 ( @'<newline>...<newline>'@):

Start-Process -Wait -FilePath $npp -ArgumentList @"
  "C:\bad boys\file1.txt" "C:\bad boys\file2.txt"
"@
Run Code Online (Sandbox Code Playgroud)

另请注意调用的整体简化Start-Process

  • 使用 来-Wait确保同步执行(等待 Notepad++ 退出后再继续)。

    • 看起来这就是您尝试通过-PassThru与管道 to结合来执行的操作Out-Null,但这实际上不起作用,因为它只会等待Start-Process自身退出(它本身 - 与启动的进程不同 - 无论如何都会同步执行)。
  • 省略不必要的-NoNewWindow参数,该参数仅适用于启动控制台应用程序(以防止打开新的控制台窗口);Notepad++ 是一个GUI应用程序。

请注意,此处使用Start-Process(而不是直接调用)的唯一充分理由是需要同步执行:Start-Process -Wait使 GUI 应用程序的启动也同步,而直接调用则仅控制台应用程序同步执行

如果您不需要等待 Notepad++ 退出,直接调用将使您的引用麻烦消失,因为所需的嵌入引用会在幕后自动执行: [1]

foreach ($file in $myfiles) {
  & $npp $file # OK, even with values with spaces
}
Run Code Online (Sandbox Code Playgroud)

然而,这个| Out-Null技巧可以有效地用于直接调用,使调用 GUI 应用程序同步[2],这使我们得到了顶部的解决方案:

foreach ($file in $myfiles) {
  & $npp $file | Out-Null  # Wait for Notepad++ to exit.
}
Run Code Online (Sandbox Code Playgroud)

[1] 然而,至少在 PowerShell 7.2.x 之前,仍然可能出现其他引用问题,即空字符串参数和值包含"字符的参数。- 看到这个答案

[2]Out-Null自动使 PowerShell 等待前一个管道段中的进程退出,以确保可以处理所有输入 - 无论该进程是控制台子系统还是 GUI 子系统应用程序,它都会这样做。由于 GUI 应用程序通常与调用控制台分离,因此不会产生任何输出,因此Out-Null不会产生不良影响。在极少数情况下,GUI 应用程序明确附加到调用控制台并在那里生成输出,您可以使用它| Write-Output来代替(如果没有输出,这也可以工作,但可能更令人困惑)。