Quoting Issues With Powershell
Quoting Issues With Powershell
Quoting Issues With Powershell
## Symptom
```powershell
# Double quotes are preserved
> Write-Host '"some quoted text"'
"some quoted text"
In order for a symbol to be received by Azure CLI, you will have to take both
PowerShell and Command Prompt's parsing into consideration. If a symbol still
exists after 2 rounds of parsing, Azure CLI will receive it.
> The stop-parsing symbol (--%), introduced in PowerShell 3.0, directs PowerShell
to refrain from interpreting input as PowerShell commands or expressions.
> When it encounters a stop-parsing symbol, PowerShell treats the remaining
characters in the line as a literal.
For instance,
```powershell
az --% vm create --name xxx
```
But keep in mind that **the command still needs to be escaped following the Command
Prompt syntax**.
```powershell
# Use --% to stop PowerShell from parsing the argument and escape double quotes
# following the Command Prompt syntax
> python.exe --% -c "import sys; print(sys.argv[1])" "\"some quoted text\""
"some quoted text"
```
## Typical issues
This causes the argument to be parsed again by Command Prompt and breaks the
argument. This typically happens when passing a URL with query string to `az`:
```powershell
> az 'https://graph.microsoft.com/v1.0/me/events?$orderby=createdDateTime&$skip=20'
--debug
az: 'https://graph.microsoft.com/v1.0/me/events?$orderby=createdDateTime' is not in
the 'az' command group.
'$skip' is not recognized as an internal or external command,
operable program or batch file.
```
1. Since there is no whitespace in the argument, PowerShell will strip the quotes
and pass the argument to Command Prompt
2. The ampersand `&` is parsed again by Command Prompt as a [command separator]
(https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-
xp/bb490954(v=technet.10)#using-multiple-commands-and-conditional-processing-
symbols)
3. `b` is treated as a separate command by Command Prompt, instead of part of the
argument
```powershell
> az "a&b" --debug
az: 'a' is not in the 'az' command group.
'b' is not recognized as an internal or external command,
operable program or batch file.
```
```cmd
>az a&b --debug
az: 'a' is not in the 'az' command group.
'b' is not recognized as an internal or external command,
operable program or batch file.
```
To solve it:
```powershell
# When quoted by single quotes ('), double quotes (") are preserved by PowerShell
and sent
# to Command Prompt, so that ampersand (&) is treated as a literal character
> az '"a&b"' --debug
Command arguments: ['a&b', '--debug']
# With a whitespace in the argument, double quotes (") are preserved by PowerShell
and
# sent to Command Prompt
> az "a&b " --debug
Command arguments: ['a&b ', '--debug']
This typically happens when passing a JSON to `az`. This is because double quotes
within the JSON string are lost when calling a native `.exe` file within
PowerShell.
```powershell
# Wrong! Note that the double quotes (") are lost
> python.exe -c "import sys; print(sys.argv)" '{"key": "value"}'
['-c', '{key: value}']
```
```cmd
>python.exe -c "import sys; print(sys.argv)" "{"key": "value"}"
['-c', '{key: value}']
```
To solve it:
```powershell
# Escape double quotes (") with backward-slashes (\) as required by Command Prompt,
# then quote the string with single quotes (') as required by PowerShell
> python.exe -c "import sys; print(sys.argv)" '{\"key\": \"value\"}'
['-c', '{"key": "value"}']
```powershell
# Wrong!
> az '{"key": "value"}' --debug
Command arguments: ['{key: value}', '--debug']
# Correct
> az '{\"key\": \"value\"}' --debug
Command arguments: ['{"key": "value"}', '--debug']
For complex arguments like JSON string, the best practice is to use Azure CLI's
`@<file>` convention to load from a file to bypass the shell's interpretation.
```powershell
az ad app create ... --required-resource-accesses "@manifest.json"
```
```powershell
Get-Content -Path manifest.json | az ad app create ... --required-resource-accesses
"@-"
```