Home > database >  [Environment]::SetEnvironmentVariable Docker on Windows
[Environment]::SetEnvironmentVariable Docker on Windows

Time:10-21

In my dockerfile I have the line

RUN [Environment]::SetEnvironmentVariable("Path", $env:Path ";C:\oracle\instantclient_19_10", "Machine")

I get this returned, even though when I run the above command in PowerShell everything "just works"

At line:1 char:114
  ...  = 'SilentlyContinue'; [Environment]::SetEnvironmentVariable(Path, $e ...
                                                                   ~
Missing ')' in method call.
At line:1 char:114
  ... SilentlyContinue'; [Environment]::SetEnvironmentVariable(Path, $env:P ...
                                                               ~~~~
Unexpected token 'Path' in expression or statement.
At line:1 char:118
  ... ilentlyContinue'; [Environment]::SetEnvironmentVariable(Path, $env:Pa ...
                                                                  ~
Missing argument in parameter list.
At line:1 char:162
  ... entVariable(Path, $env:Path   ;C:\oracle\instantclient_19_10, Machine ...
                                                                  ~
Missing argument in parameter list.
At line:1 char:171
  ... ntVariable(Path, $env:Path   ;C:\oracle\instantclient_19_10, Machine)
                                                                          ~
Unexpected token ')' in expression or statement.
      CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordEx 
   ception
      FullyQualifiedErrorId : MissingEndParenthesisInMethodCall

CodePudding user response:

The error message implies two things:

  • PowerShell is configured as your default shell in your dockerfile (by default it is cmd.exe)

  • However, the " characters were stripped from your PowerShell command, which broke it.

Therefore, escape the " character as \":

RUN [Environment]::SetEnvironmentVariable(\"Path\", $env:Path   \";C:\oracle\instantclient_19_10\", \"Machine"\)

Alternatively, you can simply use '-quoting in this case:

RUN [Environment]::SetEnvironmentVariable('Path', $env:Path   ';C:\oracle\instantclient_19_10', 'Machine')

As for why escaping " as \" is needed:

  • Presumably, what follows RUN is copied as-is to the powershell.exe -Command command line that is used behind the scenes.

  • During PowerShell's command-line parsing, unescaped " characters are removed before the resulting code is interpreted as PowerShell code. Thus, " characters that must be retained as part of the PowerShell code must be \"-escaped.

CodePudding user response:

Note: This answer isn't quite correct, check out the accepted answer https://stackoverflow.com/a/74142485/3684640 for the correct reason for why this is happening

This is an unfortunate clash with Docker's two forms of run commands referenced here https://docs.docker.com/engine/reference/builder/#run.

There's shell form:

RUN (shell form, the command is run in a shell, which by default is /bin/sh -c on Linux or cmd /S /C on Windows)

And there's exec form

RUN ["executable", "param1", "param2"] (exec form)

In Powershell with the command you're trying to use "[Environment]" is at the beginning which makes Docker think we are in exec form.

A potential fix that works is

RUN ["powershell.exe", "[Environment]::SetEnvironmentVariable(\"Path\", $env:Path \";C:\\oracle\\instantclient_19_10\", \"Machine\")"]

Which works by using exec form instead of shell form, since this is in json syntax we have to escape all the necessary characters as well.

  • Related