As an aside: A fully robust solution that works in any invocation scenario would indeed require use of -EncodedCommand
with a string that is the Base64 encoding of the command string's UTF16-LE byte representation - but you've stated that creating such a string is not an option for you.
If you were to call from PowerShell, you could more simply use a script block (see bottom).
Update: The OP's own answer now contains a robust, if nontrivial, solution based on careful string substitutions.
The answer below may still be of interest for simpler scenarios and for background information on quoting requirements and pitfalls.
Using the scenario from your question, this simpler solution should do (verified from cmd.exe
- we still don't know where you're calling PowerShell from, but I expect it to work if there's no shell involved):
powershell.exe -command "Set-Clipboard \"this is`r`na test\""
As for other special characters:
'
can be embedded as-is - no escaping needed
"
requires escaping as `\"
$
as `$
, but only if you want it to be treated as a literal (the same escaping that would apply in a regular double-quoted PowerShell string)
If your use case requires passing an arbitrary preexisting string, you'd have to employ string substitution to perform the above escaping - including replacing embedded newlines with literal `r`n
.
If there is no shell involved (such as with subprocess.check_output()
from Python), the above rules should suffice and make for a robust solution (assuming you only use printable characters and there are no character-encoding issues).
From cmd.exe
, however, a fully robust solution that doesn't use -EncodedCommand
requires extra, nontrivial work, due to its lack of proper parsing of embedded double quotes:
The following cmd.exe
metacharacters typically require ^
-escaping, but sometimes the mustn't be escaped:
& | < >
In the following example, &
requires ^
-escaping:
powershell.exe -command "Set-Clipboard \"this is`r`na ^& test\""
However, if your string also has embedded (and escaped) "
chars., whether these characters require^
-escaping depends on their placement relative to the embedded "
; note how in the following example &
need not be ^
-escaped and indeed must not be, because the ^
would then become part of the string:
powershell.exe -command "Set-Clipboard \"this is`r`na 3`\" & test\""
Anticipating these variations algorithmically is a nontrivial undertaking.
Additionally, if your string had %...%
tokens that look like cmd.exe
-style environment variables - e.g., %FOO%
- but you want to treat them as literals, the %
cannot be escaped.
There is a workaround that may work, but it again depends on the presence and placement of embedded "
chars.
In the following example, the "^ disrupter" trick can be used to prevent expansion of %OS%
:
powershell.exe -command "Set-Clipboard \"do not expand: %^OS%\""
However, if an embedded "
precedes it, the workaround becomes ineffective (the ^
is retained), and there's no direct fix that I know of in this scenario:
powershell.exe -command "Set-Clipboard \"do not expand: 3`\" %^OS%\""
You'd have to split the string into multiple pieces to break the %OS%
token apart and concatenate the pieces via a PowerShell expression:
powershell.exe -command "Set-Clipboard (\"do not expand: 3`\" %\" + \"OS%\")"
Algorithmically, you could use placeholder chars. that you then replace as part of the PowerShell command, a technique you've used in your own answer.
As an aside:
Extra escaping would be required if you wanted to execute this from PowerShell:
powershell.exe -command "Set-Clipboard \`"this is`r`na test\`""
However, from PowerShell it's not hard to construct a Base64-encoded string to pass to
-EncodedCommand
, but there's an even easier method: use a script block to pass your command; no extra quoting requirements apply in that case, because -EncodedCommand
is then automatically used behind the scenes (along with -OutputFormat Xml
).
Do note that this only works from within PowerShell.
powershell.exe -command { Set-Clipboard "this is`r`na test" }