简体   繁体   中英

How to solve problem with quotes in arguments on calling a PowerShell script with -File option?

I want to call a small PowerShell (v5.1) script from Windows 10 Pro command line with arguments.

param($ReqURL, $JSONString) 
Write-Host $ReqURL # for debug 
Write-Host $JSONString # for debug 
Invoke-RestMethod  -Uri $ReqURL -Method Patch -ContentType "application/json" -Body $JSONString

Calling the script in a PowerShell console works fine:

.\http-patch.ps1  -ReqURL myRESTApi -JSONString '{"lastname": "Bunny"}'

Calling the script from the Windows Command Prompt ( cmd.exe ) works when I escape the double quotes, like this:

PowerShell .\http-patch.ps1 -ReqURL myRESTApi  -JSONString '{\"lastname\": \"Bunny\"}'

But when I use the -File option, it fails because the $JSONString inside the script is equal to '{"lastname": :

PowerShell -File "C:\work\LV Demo\http-patch.ps1" -ReqURL myRESTApi  -JSONString '{\"lastname\": \"Bunny\"}'

I assume here are some problems with quotes, but I can't find the right way.

When you use the -File parameter of powershell.exe , the Windows PowerShell CLI , only double quotes ( " ) are recognized as having syntactic function when calling from outside PowerShell , such as from cmd.exe :

Therefore, switch from ' to " (the embedded " chars. require escaping as \" (sic) either way):

:: From cmd.exe
PowerShell -File "C:\work\LV Demo\http-patch.ps1" -JSONString "{\"lastname\": \"Bunny\"}" -ReqURL myRESTApi

By contrast, when you use -Command , '...' strings are recognized, after unescaped " chars. - the only ones with syntactic function during initial command-line parsing - have been stripped , because the resulting tokens are then interpreted as PowerShell code .

For guidance on when to use -Command vs. -File and the differences in resulting parsing, see this answer .


From inside PowerShell, there's rarely a need to to call another PowerShell instance , given that .ps1 files can be invoked directly, in-process.

In cases where you do need to call the CLI from inside PowerShell - say you need to call the CLI of the other PowerShell edition , PowerShell (Core)'s pwsh.exe , from powershell.exe or vice versa - the best choice is to use a script block ( {... } ) (which works only when calling from inside PowerShell), because that:

  • allows you to focus solely on PowerShell's own quoting and escaping requirements.
  • supports receiving typed output (objects other than strings ), behind-the-scenes XML-based serialization, albeit with limited type fidelity - see this answer .
# From PowerShell
# Note how the " chars. now need NO escaping.
# (If you were to use a "..." string, you'd escape them as `" or "")
PowerShell { 
 & C:\work\LV Demo\http-patch.ps1" -JSONString '{"lastname": "Bunny"}' -ReqURL myRESTApi 
}

While you can call via individual arguments , analogous to how you must call from outside PowerShell, you'll not only lose the benefit of typed output, but you'll also run in a longstanding bug up to PowerShell 7.2.x that requires manual escaping of embedded " chars. as \ when calling external programs - see this answer - as evidenced by one of your own attempts (here, using '...' is perfectly fine, because PowerShell recognizes it):

# !! Note the unexpected need to \-escape the embedded " chars.
PowerShell -File .\http-patch.ps1 -JSONString '{\"lastname\": \"Bunny\"}' -ReqURL myRESTApi  

# Variant with double quotes.
# !! Note the *double* escaping: first with ` - for the sake of PowerShell itself -
# !! then with \ due to the bug.
PowerShell -File .\http-patch.ps1 -JSONString "{\`"lastname\`": \`"Bunny\`"}" -ReqURL myRESTApi  

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM