【问题标题】:How to pass an array to the arguments in Start-Process in Powershell?如何将数组传递给 Powershell 的 Start-Process 中的参数?
【发布时间】:2022-01-25 12:03:24
【问题描述】:

我正在编写一个脚本来播放播放器中的某些文件。我使用 Get-ChildItem 来获取文件名数组。然后我想用 Start-Process 来播放这些文件。但是,如何将这些文件名添加到播放器程序的参数中?

我用了Start-Process -FilePath "C:\Program Files\DAUM\PotPlayer\PotPlayerMini64.exe" -ArgumentList $selected_items,但是好像不行,文件也没有播放。

注意文件名中有空格。

【问题讨论】:

    标签: powershell


    【解决方案1】:

    语法-明智地,你的方法应该工作,但不,由于不幸的错误,仍然存在于 PowerShell 7.2 中 - 请参阅 GitHub issue #5576。

    • 虽然将一个数组参数传递给Start-Process的-ArgumentList参数确实会导致数组元素作为单个参数传递(这通常是外部CLI 需要多个文件参数),在构建最终用于调用的命令行时,不应用元素周围的必要双引号在幕后。

    • 此外,为了稳健性,您应该使用存储在$selected_items 中的对象的.FullName 属性,以确保通过完整路径,因为 -在 Windows PowerShell 中,根据情况 - Get-ChildItem 的输出对象可能仅字符串化为文件 name - 请参阅 this answer。

    解决方法:将单个参数传递给-ArgumentList,您可以在其中编码所有传递参数,使用嵌入式双引号。

    Start-Process `
      -FilePath "C:\Program Files\DAUM\PotPlayer\PotPlayerMini64.exe" `
      -ArgumentList ($selected_items.ForEach({ '"{0}"' -f $_.FullName }) -join ' ')
    

    退后一步:

    如果PotPlayerMini64.exe 是Windows GUI(-子系统)应用程序,则根本不需要Start-Process,因为即使直接调用也会起作用异步(即,程序将启动,控制权将立即返回 PowerShell;相反,如果您想等待程序退出,请使用Start-Process -Wait)。

    & "C:\Program Files\DAUM\PotPlayer\PotPlayerMini64.exe" $selected_Items.FullName
    

    请注意,在这样的直接调用中,PowerShell确实根据需要在幕后执行必要的双引号。

    注意:我不清楚将多个文件路径传递给PotPlayerMini64.exe单独是否也开始播放 - 下一节中的替代解决方案可以确保这一点。


    基于剪贴板的替代解决方案:

    根据PotPlayerMini64.exe 的available command-line options[1]判断,以下可能有效(我无法亲自验证):

    /clipboard :将剪贴板中的内容附加到播放列表中并立即开始播放。

    # Copy the full names of the files of interest to the clipboard.
    Set-Clipboard -Value $selected_items.FullName
    
    # Launch the player and tell it to start playback of the files on the clipboard.
    # Parameters -FilePath and -ArgumentList are positionally implied.
    Start-Process 'C:\Program Files\DAUM\PotPlayer\PotPlayerMini64.exe' /clipboard
    

    有一些与文件参数相关的选项,例如 /new、/insert 和 /add,但我不清楚它们是否 - 或者完全省略它们,就像你的尝试一样 - 自动 开始播放(可能取决于应用程序的持久配置)。


    [1] 注意这不是官方文档;我找不到后者。

    【讨论】:

      【解决方案2】:

      你可以ForEach-Object:

      Get-ChildItem . | ForEach-Object {Start-Process -FilePath "C:\Program Files\DAUM\PotPlayer\PotPlayerMini64.exe" -ArgumentList $_.FullName}
      

      【讨论】:

      • @dspjm 是的,为什么会有人同时收听多个音频文件?
      • 典型的用例是提交多个文件作为播放列表,然后一个接一个地播放。 PotPlayerMini64.exe's command-line syntax 无疑能够接收多个文件作为参数。
      • @mklement0 当你在回答中说“可能有用”时,你怎么能说“毫无疑问”?
      • 也许我应该说它毫无疑问设计基于它的命令行语法接受多个文件(假设源是权威的 - 这是我能找到的最好的 - 做告诉我们你是否知道更好的)。我的回答中的可能来自我无法尝试命令myself。但是,如果您确实可以访问PotPlayerMini64.exe,请尝试一下,并请报告。
      • @mklement0 虽然理论上文件是按顺序调用的,但程序确实会将文件添加到播放列表中,因此它适用于 Potplayer。无论如何,您编辑的答案中的方法似乎更好。感谢您的努力。
      【解决方案3】:

      您不需要 start-process(另外,-argumentlist 无法轻松处理带有空格的文件名)。

      & "C:\Program Files\DAUM\PotPlayer\PotPlayerMini64.exe" 
      C:\Program` Files\DAUM\PotPlayer\PotPlayerMini64.exe
      $env:path += ';C:\Program Files\DAUM\PotPlayer'; PotPlayerMini64
      

      即使使用启动进程,它也会因程序而异。例如,Emacs 可以采用多个文件参数,以空格分隔。如果文件名有空格,则需要双引号。外部程序不知道数组是什么,并且 start-process 将它们转换为一个字符串,每个元素之间有空格。

      start emacs file1,file2,'"my file"'
      
      get-wmiobject win32_process | ? name -eq emacs.exe | % commandline
      "c:\program files\emacs\bin\emacs.exe" file1 file2 "my file"
      
      ps emacs | % commandline  # ps 7
      "c:\program files\emacs\bin\emacs.exe" file1 file2 "my file"
      

      【讨论】:

      • 他的实际问题呢?(;
      猜你喜欢
      • 2016-12-18
      • 1970-01-01
      • 2017-10-08
      • 2017-07-28
      • 2020-11-07
      • 1970-01-01
      • 2022-01-23
      • 2017-07-11
      • 1970-01-01
      相关资源
      最近更新 更多