2

this is my first question on stackoverflow, so please be easy on me.

Problem: The call to an external EXE file from a Powershell Script should look like this.

C:\temp\someEXE.exe "batch" "B:\some path with spaces\file name with spaces.jpg" "" "C:\some other path"

My $Arguments Variable in the ps1-script looks like this.

$Arguments = '"batch"', "$Originalpath", '""', "$Outpath\$Outfile"
Start-Process -Wait -FilePath "C:\Temp\SomeExe.exe" -ArgumentList "$Arguments"

Argument 1 "batch" and 3, the empty "" works fine with the '""' (single - double - double - single).

But when i use the '"$Variable"' (single-double double-single) it is not interpreted according to the Quoting Rules (https://learn.microsoft.com/de-de/powershell/module/microsoft.powershell.core/about/about_quoting_rules?view=powershell-7.1)

So my question is: How do i get from $Originalpath to "B:\some path with spaces\file name with spaces.jpg" incl. the ""

Thank you in advance

UPDATE: When i add a line to write the Parameters to a logfile, this line gives me what i need.

Write-output '"batch"',`"$Original`",'""',`"$AIAusgabepfad\$Originaldatei$Originaltyp`" | Out-file C:\Temp\Startup.log -append

But when i try to my $Arguments in the same way, the scriptwindow pops up and disapears in the same second.

1 Answers1

0

Generally: To synchronously execute console applications or batch files, call them directly (C:\temp\someEXE.exe ...), do not use Start-Process - see this answer and this GitHub docs issue detailing appropriate vs. non-appropriate use cases and requesting that guidance be added to the Start-Process help topic.

  • That said, note that, as of PowerShell 7.1, passing empty-string arguments ("") is broken and requires workaround '""'.

  • Similarly, passing arguments with embedded " chars. is also broken, as discussed in this answer.

  • An opt-in fix is now being discussed in GitHub issue #14747, but note that if you opt into that fix, the old workarounds will break.


If you do need to use Start-Process:

While the -ArgumentList parameter is array-typed ([string[]]), allowing you to pass arguments individually - which you've tried to take advantage of - unfortunately, Start-Process doesn't handle such individually passed arguments properly if they contain embedded spaces (see GitHub issue #5576), so the robust solution is to use a single -ArgumentList argument comprising all arguments, with embedded double-quoting, as necessary (see this answer for a more detailed discussion).

Start-Process -Wait -FilePath "C:\Temp\SomeExe.exe" -ArgumentList `
  "batch `"$Originalpath`" `"`" `"$Outpath\$Outfile`""

Note that this method of passing arguments - as a single string with embedded quoting and escaping passed to Start-Process -ArgumentList - is not subject to the bugs that plague direct invocation: the resulting string is passed through to the process as-is (on Windows).

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Thank you for the right direction. I need the Start-Process because i need the -wait option to limit the number of concurent runs. I tried to pass the arguments directly (and not via the $Arguments Variable) This is the version that is working for me now. Start-Process -Wait -FilePath "C:\Temp\SomeEXE.exe" -ArgumentList '"batch"',`"$Originalpath`",'""',`"$Outpath\$Outfile`" – Jürgen Mayr Feb 22 '21 at 09:09
  • @JürgenMayr, yes, if the application is a GUI-subsystem application, you need `Start-Process -Wait` to execute it synchronously (with console-subsystem applications, invocation is synchronous by default). The command you're showing would break if any of the values contained in the references variables contained _spaces_ (which is the bug that the answer links to) - passing everything as a _single_ `-ArgumentList` argument with _embedded quoting_, as shown in the answer, avoids that. – mklement0 Feb 22 '21 at 12:53