I have been learning and using PowerShell more and more on my daily computer work, even on linux, and I am liking the experience very much but I got severely annoyed at what apparently looked like a bug but I then found it to be a known “issue” or “feature” if we like.

Now, presume we have a program that prints its arguments to the console, in C it would look like this:

#include <stdio.h>
void main(int argc, char** argv)
{
  for (int i=0; i < argc; i++)
  {
    printf("%s\r\n", argv[i]);
  }
}

Calling this program with some arguments will yield us to this output:

# SH
$ ./print-argv Hello World
/home/user/print-argv
Hello
World

# PowerShell
> ./print-argv Hello World
/home/user/print-argv
Hello
World

If we wanted to give it a double quote " as the first argument, we would need to escape it, on UNIX shell it would be using the \ character, and on PowerShell it would be the ` character.

# SH
$ ./print-argv \" Hello World
/home/user/print-argv
"
Hello
World

# PowerShell
> ./print-argv `" Hello World
/home/user/print-argv
"
Hello
World

So far so good, everything is working as expected. Now, on Windows, many programs have the bad behaviour of freeing the console before terminating so the script will continue executing before the program has terminated so you would need to use the Start-Process -Wait cmdlet. So we just copy & paste the command line we used before and change it to the Start-Process syntax:

> Start-Process ./print-argv -Wait -ArgumentList `", Hello, World
/home/user/print-argv
 Hello World

What? Suddenly 3 arguments become 1 argument and the " character is nowhere to be seen? Oh well, if we go to the Start-Process documentation it warns us about double quotes that need to be escaped, so we do it again.

> Start-Process ./print-argv -Wait -ArgumentList "`"", Hello, World
/home/user/print-argv
 Hello World

… Same result. Then on the same help document it links us to the quoting rules and at the very very bottom of the page, we find another page that involves “external commands” and parsing, which Start-Process is not but it has a fair warning about a .NET class ProcessStartInfo which I presume Start-Process uses:

The backslash (\) character isn’t recognized as an escape character by PowerShell. It’s the escape character used by the underlying API for ProcessStartInfo.Arguments.

So apparently the solution is… Mixing two styles of escaping. Because reasons.

> Start-Process ./print-argv -Wait -ArgumentList \`", Hello, World
/home/user/print-argv
"
Hello
World

There we have it, the expected output, using an unexpected input.