Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Powershell GetEnvironmentVariable vs $Env

I have run into a couple cases where I am trying to use a command via command line, but the command is not recognized. I have narrowed it down to an issue with environment variables. In each case, the variable is present when I retrieve the variable with the underlying C# method, but not with the shorthand, $env:myVariable

For example, if I retrieve the variable like this, I will get a value.

 [Environment]::GetEnvironmentVariable('ChocolateyInstall', 'Machine')

But, if I retrieve the variable like this, nothing is returned

$env:ChocolateyInstall

I then have to do something like this to to get my command to work.

$env:ChocolateyInstall = [Environment]::GetEnvironmentVariable('ChocolateyInstall', 'Machine')

I have not been able to find a good explanation as to why I have to do this. I've looked at this documentation, but nothing stands out to me. Ideally, I would like to install a CLI and then not have to deal with checking for and assigning environment variables for the command to work.

like image 280
jellybeans Avatar asked Jul 21 '20 02:07

jellybeans


People also ask

What does $ENV do in PowerShell?

The $env:PSModulePath environment variable contains a list of folder locations that are searched to find modules and resources. By default, the effective locations assigned to $env:PSModulePath are: System-wide locations: These folders contain modules that ship with PowerShell.

How do I check environment variables in PowerShell?

Environment] to retrieve the specific or all environment variables. To retrieve all environment variables use GetEnvironmentVariables() class. To get the specific environment variable using . Net method use GetEnvironmentVariable() method.

How do you pass an environment variable in PowerShell?

To set the environmental variable using PowerShell you need to use the assignment operator (=). If the variable already exists then you can use the += operator to append the value, otherwise, a new environment variable will be created.

How do I find the PATH variable in PowerShell?

List $Env:Path with PowerShell. You can also see path values in the Control Panel; navigate to the System section and then click on the link to 'Advanced system settings'.


Video Answer


1 Answers

When opening a PowerShell session, all permanently stored environment variables1 will be loaded into the Environment drive (Env:) of this current session (source):

The Environment drive is a flat namespace containing the environment variables specific to the current user's session.

The documentation you linked states:

When you change environment variables in PowerShell, the change affects only the current session. This behavior resembles the behavior of the Set command in the Windows Command Shell and the Setenv command in UNIX-based environments. To change values in the Machine or User scopes, you must use the methods of the System.Environment class.

So defining/changing an environment variable like this:

$env:ChocolateyInstall = [Environment]::GetEnvironmentVariable('ChocolateyInstall', 'Machine')

Will change it for the current session, thus being immediately effective, but will also only be valid for the current session.

The methods of [System.Environment] are more fine grained. There you can choose which environment variable scope to address. There are three scopes available:

  • Machine
  • User
  • Process

The Process scope is equivalent to the Environment drive and covers the environment variables available in your current session. The Machine and the User scope address the permanently stored environment variables1. You can get variables from a particular scope like this:

[Environment]::GetEnvironmentVariable('ChocolateyInstall', 'Machine')

And set them with:

[Environment]::SetEnvironmentVariable('ChocolateyInstall', 'any/path/to/somewhere', 'Machine')

If you want to have new variables from the Machine or User scope available in your current PowerShell session, you have to create a new one. But don't open a new PowerShell session from your current PowerShell session, as it will then inherit all environment variables from your current PowerShell session (source):

Environment variables, unlike other types of variables in PowerShell, are inherited by child processes, such as local background jobs and the sessions in which module members run. This makes environment variables well suited to storing values that are needed in both parent and child processes.

So, to address the problem you described, you most probably changed your permanently stored environment variables1, while already having an open PowerShell session. If so, you just need to open a new (really new, see above) session and you will be able to access your environment variables via the Environment drive. Just to be clear, opening a new session will even reload environment variables of the Machine scope. There is no reboot required.


1 That are the environment variables you see in the GUI when going to the System Control Panel, selecting Advanced System Settings and on the Advanced tab, clicking on Environment Variable. Those variables cover the User and the Machine scope. Alternatively, you can open this GUI directly by executing:

rundll32 sysdm.cpl,EditEnvironmentVariables
like image 187
stackprotector Avatar answered Nov 15 '22 03:11

stackprotector