2

I am writing a script to play certain files in a player. I use Get-ChildItem to get an array of file names. Then I want to use Start-Process to play these files. However, how can I add these file names to the arguments of the player program?

I used Start-Process -FilePath "C:\Program Files\DAUM\PotPlayer\PotPlayerMini64.exe" -ArgumentList $selected_items but it seems it doesn't work and the files are not played.

Notice there are spaces in the file names.

dspjm
  • 5,473
  • 6
  • 41
  • 62

3 Answers3

5

Syntax-wise, your approach should work, but doesn't, due to an unfortunate bug, still present in PowerShell 7.2 - see GitHub issue #5576.

  • While passing an array of arguments to Start-Process's -ArgumentList parameter does cause the array elements to be passed as individual arguments (which is usually how external CLIs expect multiple file arguments), the necessary double-quoting around elements with spaces is not applied when the command line ultimately used for invocation is constructed behind the scenes.

  • Also, for robustness you should use the .FullName property of the objects stored in $selected_items, so as to ensure that full paths are passed, because - in Windows PowerShell, situationally - Get-ChildItem's output objects may stringify to the file name only - see this answer.

Workaround: Pass a single argument to -ArgumentList, in which you encode all pass-through arguments, using embedded double-quoting.

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

Taking a step back:

If PotPlayerMini64.exe is a Windows GUI(-subsystem) application, you don't need Start-Process at all, because even direct invocation will then act asynchronously (i.e., the program will launch, and control will return to PowerShell right away; conversely, if you wanted to wait for the program to exit, use Start-Process -Wait).

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

Note that in direct invocations such as this, PowerShell does perform the necessary double-quoting behind the scenes, on demand.

Note: I'm unclear on whether passing multiple file paths to PotPlayerMini64.exe alone also starts playback - the alternative solution in the next section may ensure that.


Alternative, clipboard-based solution:

Judging by PotPlayerMini64.exe's available command-line options[1], the following may work (I cannot personally verify):

/clipboard :Appends content(s) from clipboard into playlist and starts playback immediately.

# 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

There are file-arguments-related options such as /new, /insert, and /add, but it's unclear to me whether they - or omitting them altogether, as in your attempt - automatically start playback (may depend on the application's persistent configuration).


[1] Note that this is not the official documentation; I couldn't find the latter.

mklement0
  • 382,024
  • 64
  • 607
  • 775
2

You can ForEach-Object:

Get-ChildItem . | ForEach-Object {Start-Process -FilePath "C:\Program Files\DAUM\PotPlayer\PotPlayerMini64.exe" -ArgumentList $_.FullName}
Paolo
  • 21,270
  • 6
  • 38
  • 69
  • @dspjm yeah, why on earth would someone listen to multiple audio files at the same time? – Paolo Dec 25 '21 at 15:55
  • The typical use case is to submit multiple files _as a playlist_, and then play one after the other. [`PotPlayerMini64.exe`'s command-line syntax](https://github.com/red217/EmbyExternalPlayerLauncher/issues/2) is undoubtedly capable of receiving multiple files as arguments. – mklement0 Dec 25 '21 at 17:22
  • @mklement0 how can you say "undoubtedly", when in your answer you say "may work" ? – Paolo Dec 25 '21 at 17:28
  • 1
    Perhaps I should have said its undoubtedly _designed_ to accept multiple files, based on its command-line syntax (assuming the source is authoritative - it's the best I could find - do tell us if you know a better one). The _may_ in my answer comes from my inability to try the command _myself_. But if you do have access to `PotPlayerMini64.exe`, do try it, and please report back. – mklement0 Dec 25 '21 at 17:31
  • And, to recapitulate what the question asks for: (a) pass _multiple_ files and (b) start playback. – mklement0 Dec 25 '21 at 17:38
  • I also forgot that `-ArgumentList` is buggy with respect to arguments _with spaces_ (as stipulated in the question), so `-ArgumentList $_.FullName` won't work. (I've amended my answer). – mklement0 Dec 25 '21 at 18:10
  • 1
    @mklement0 Although theoretically the files are invoked sequentially, the program does add the files to the playlist, therefore it works in the Potplayer's case. Anyway, the method in your edited answer seems better. Thanks for your effort. – dspjm Dec 26 '21 at 09:54
1

You don't need start-process (plus, -argumentlist doesn't handle filenames with spaces as easily).

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

Even using start-process, it varies with the program. For example, Emacs can take multiple file arguments, separated by spaces. If the filename has a space, it would need to be double quoted. External programs don't know what arrays are, and start-process converts them to one string with spaces in between each element.

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"
js2010
  • 23,033
  • 6
  • 64
  • 66