Tuesday, January 30, 2024

[SOLVED] How to add a quotation mark in PowerShell?

Issue

I wanted to make a command to install the Scoop package manager for Windows

It should be run from the cygwin shell It works like this:

  1. Requests administrator permission
  2. Opens a PowerShell window
  3. Runs the Scoop installation command

I made this command, it looks like this:
powershell -NoProfile -ExecutionPolicy Bypass -Command 'Start-Process powershell -ArgumentList "-NoProfile -ExecutionPolicy Bypass -NoExit -Command iex ""& {$(irm get.scoop.sh)} -RunAsAdmin""" -Verb RunAs -Wait'

This command runs, but there is one problem - there is no quotation mark next to the "&" symbol

Error photo

Error text:

At line:1 char:5
+ iex & {# Issue Tracker: https://github.com/ScoopInstaller/Install/iss ...
+     ~
The ampersand (&) character is not allowed. The & operator is reserved for future use; wrap an ampersand in double quot
ation marks ("&") to pass it as part of a string.
At line:339 char:30
+         set args=%args:(=``(%,
+                              ~
Missing argument in parameter list.
At line:689 char:31
+ $ErrorActionPreference = 'Stop'
+                               ~
The string is missing the terminator: '.
At line:241 char:30
+         if ($retries -eq 10) {
+                              ~
Missing closing '}' in statement block or type definition.
At line:240 char:29
+     while ($retries -le 10) {
+                             ~
Missing closing '}' in statement block or type definition.
At line:108 char:33
+ function Test-ValidateParameter {
+                                 ~
Missing closing '}' in statement block or type definition.
At line:1 char:7
+ iex & {# Issue Tracker: https://github.com/ScoopInstaller/Install/iss ...
+       ~
Missing closing '}' in statement block or type definition.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : AmpersandNotAllowed

As you can see, the script is loaded and enclosed in curly braces, but still not executed because there is no quotation mark next to the "&" character

And now it is interpreted as follows:

iex & {<scoop installation script>} -RunAsAdmin

And it should be like this:

iex "& {<scoop installation script>} -RunAsAdmin"

I took the script itself from the official Scoop installation documentation - https://github.com/ScoopInstaller/Install#for-admin

So please help me put quotes in my install command 🙏


Thank you in advance!


Solution

Preface:

  • Note the Cygwin context, which means that the syntax rules of POSIX-compatible shells such as bash initially apply; notably this means:
    • The embedded " are automatically escaped as \" for the outer powershell.exe process command line.
    • When the outer powershell.exe process then makes the inner powershell.exe call, it constructs a raw Windows process command line, where manual \-escaping of embedded " chars. is necessary.

Solution:

  • Escape the embedded "" as \"":

    • "" (as used by you) escapes the " for inclusion inside the enclosing "..." string in the outer powershell.exe call

    • \ then escapes the resulting " for use with the inner powershell.exe -Command CLI call.

      • With -Command, the PowerShell CLI removes unescaped " instances during command-line parsing, before interpreting the resulting code as PowerShell code; this is the initial problem you ran into - see this answer for details.
    • Note: \`" is an alternative to \"", given that " inside "..." can also be escaped as `"

  • `-escape the $ in $(irm get.scoop.sh)

    • Because the outer powershell.exe call uses "..." quoting around its -ArgumentList value, the $ inside it must be `-escaped in order to prevent premature expansion (interpolation), given that the intent is for the inner - then-elevated - powershell.exe call to interpret the $(...) subexpression.
powershell -NoProfile -ExecutionPolicy Bypass -Command 'Start-Process powershell -ArgumentList "-NoProfile -ExecutionPolicy Bypass -NoExit -Command iex \""& {`$(irm get.scoop.sh)} -RunAsAdmin\""" -Verb RunAs -Wait'


Answered By - mklement0
Answer Checked By - David Marino (WPSolving Volunteer)