19 March 2022

PowerShell Escape

Everyone need to escape their PowerShell sometimes
especially if a string contains $ or “

David Moss 2022

The here-string

PowerShell has a special construct for multi-line strings called the here-string

$thing = @"
$greeting = "Hello World"
write-output ($greeting)
"@

Above a variable ($thing) is declared and initialised with a multi-line String.
Note the first thing after the = sign is an @ character followed by a double-quote character.
Also note there is nothing else on that line.
The here-string continues across multiple lines and can contain any character sequence, even quote characters.
The here-string is terminated by a double-quote character followed by an @ character on a line by themselves.

The here-string is very useful but it can be tricky. After entering the above in a script, running the command:

write-output $thing

results in

 = "Hello World"
write-output ()

which is not what most people expect. Even worse, trying to use the here-string to construct a scriptblock results in a nasty error:

Invoke-Command -ScriptBlock ([ScriptBlock]::Create($thing))

results in:

Line |
   8 |  Invoke-Command -ScriptBlock ([ScriptBlock]::Create($thing))
     |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | Exception calling "Create" with "1" argument(s): "At line:2 char:15 + write-output (); +               ~ An expression was expected after '('."

Now that is an obscure error! It is caused by not ‘escaping’ the special characters in the here-string properly.
The escape character in PowerShell is the grave character, `. That is not a flyspeck before the full stop character in the last sentence. It is the grave character, or ‘back-tick’, often found around the top left of the keyboard. On the Mac keyboard it shared a key with the tilde character, ~. Lets try again with escaping:

$thing = @"
`$item = `"hi there`";
write-output (`$item);
"@

Write-Output ($thing)

Invoke-Command -ScriptBlock ([ScriptBlock]::Create($thing))

which results in:

$item = "hi there";
write-output ($item);
hi there

I have escaped the $ character and the ” characters inside the here-string with the ` character.