I have a project where I'm trying to dynamically prepare a Powershell script, then write it out to a file for later execution.
Here's a minimal example of the issue:
# The string that I want to write out, having most special characters
$_output_str = "~@#$%&*()-_=+{}[]<>?/.,'`"``;!"
# Write it out directly
Write-Output "$_output_str"
This is putting a string with escaped special characters into a variable, then writing the value of that variable out to stdout. It works as expected:
~@#$%&*()-_=+{}[]<>?/.,'"`;!
Now, let's try storing that command in a file for later execution.
# The string that I want to write out, having most special characters
$_output_str = "~@#$%&*()-_=+{}[]<>?/.,'`"``;!"
# Turn it into a string command
$_cmd = "Write-Output `"$_output_str`""
# Write the command out to a file
"$_cmd" | Out-File "execution.ps1"
And now let's try executing that file:
powershell.exe .\execution.ps1
This throws an error:
At C:\{MYPATH}\execution.ps1:1 char:43
+ Write-Output "~@#$%&*()-_=+{}[]<>?/.,'"`;!"
+ ~
The string is missing the terminator: ".
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : TerminatorExpectedAtEndOfString
OK, so let's look at the content that was written to the file. This is what execution.ps1 contains:
Write-Output "~@#$%&*()-_=+{}[]<>?/.,'"`;!"
Notice that the " and the backtick near the end of the string are no longer escaped. So for some reason, when creating the $_cmd string, it got rid of my escape sequences.
How can I prevent this from happening?