# Environment Variables in Powershell
by Seth Kenlon

Environment variables are global settings for your Linux, Mac, or Windows computer, stored for the system shell to use when executing commands.
Many are set by default during installation or user creation.
For instance, your home directory is set as an environment variable when you log in.

On Windows with Powershell:

```
PS C:\Users\bogus> Get-Variable HOME -valueOnly
C:\Users\bogus
```

On Linux: 

```
pwsh> Get-Variable HOME -valueOnly
HOME=/home/seth
```

On a Mac OS:

```
pwsh> Get-Variable HOME -valueOnly
HOME=/Users/bogus
```


You usually don't use environment variables directly, but they're referenced by individual applications and daemons as needed.
However, environment variables can be useful when you want to override default settings, or when you need to manage new settings that your system has no reason to create on its own.
This article is about environment variables in the open source Powershell environment, and so it's applicable to Powershell running on Windows, Linux, and Mac.
Users of the Bash shell should refer to my article about [Environment variables](LINK TO MY ARTICLE ABOUT ENV VAR)].
For this article, I ran Powershell on the open source operating system Linux.
The commands are the same regardless of your platform, although the output will differ (for instance, it is statistically unlikely that your username is ``seth``).



## Environment variables

Environment variables in Powershell are special kinds of variables that provide the system with information about the operating system environment. 
With environment variables, you can view and change variables in the Windows registry, as well as variables set for a particular session. 
In Powershell, environment variables are stored in the ``Env:`` drive, accessible through the **Powershell environment provider**, a subsystem of Powershell.
This isn't a physical drive, but a virtual file system.

Because environment variables exist in the ``Env:`` drive, when you reference them you must prepend ``Env:`` to the variable name.
Alternately, you can set your working location to the ``Env:`` drive with the ``Set-Location`` command so you can treat all environment variables as local variables.

```
PS> Set-Location Env:
PS> pwd

Path
----
Env:/
```

Environment variables convey information about your login session to your computer.
For instance, when an application needs to determine where to save a data file by default, it usually calls upon the ``HOME`` environment variable.
You probably never set the ``HOME`` variable yourself, and yet it exists because most environment variables are managed by your operating system.

You can view all environment variables set on your system with the ``Get-ChildItem`` command from within the ``Env:`` drive.
The list is long, so pipe the output through ``out-host -paging`` to make it easy to read:

```
PS> Get-ChildItem | out-host -paging
LOGNAME      seth
LS_COLORS    rs=0:mh=00:bd=48;5;232;38;5;
MAIL         /var/spool/mail/seth
MODULEPATH   /etc/scl/modulefiles:/etc/scl/modulefiles
MODULESHOME  /usr/share/Modules
OLDPWD       /home/seth
PATH         /opt/microsoft/powershell/6:/usr/share/Modules/bin
PSModulePath /home/seth/.local/share/powershell/Modules
PWD          /home/seth
[...]
```

If you're not in the ``Env:`` drive, then you can do the same thing by adding ``Env:`` to your command:

```
PS> Get-ChildItem Env: | out-host -paging
LOGNAME      seth
LS_COLORS    rs=0:mh=00:bd=48;5;232;38;5;
MAIL         /var/spool/mail/seth
MODULEPATH   /etc/scl/modulefiles:/etc/scl/modulefiles
```

Environment variables can be set and recalled and cleared with some of the same syntax used for normal variables.
Like other variables, anything you set during a session only applies to that particular session.
If you want to make permanent changes to a variable, you must change them in Windows Registry on Windows, or in a shell configuration file (such as ``~/.bashrc``) on Linux or Mac.
If you're not familiar with using variables in Powershell, read my [variables in Powershell](link to my VARIABLES IN POWERSHELL article) article before continuing.

## What are environment variables use for? 

Different environment variables get used by several different systems within your computer. 
Your ``Path`` variable is vital to your shell, for instance, but a lot less significant to, say, Java (which also has paths, but paths to important Java libraries rather than general system folders).
However, the ``USER`` variable is used by several different processes to identify who is requesting a service.

An installer wizard, like the open source [NSIS](https://sourceforge.net/projects/nsis/) framework, updates your environment variables when you're installing a new application.
Sometimes, when you're installing something outside of your operating system's intended tool-set, you may have to manage an environment variable yourself.
Or you might choose to add an environment variable to suit your preferences.

## Child processes 

When you create a normal variable, the variable is considered local, meaning that it's not defined outside of the shell that created it.
For example, create a variable:

```
PS> Set-Variable -Name VAR -Value "example"
PS> gv VAR -valueOnly
example
```

Launch a new shell, even from within your current shell:

```
PS> pwsh
PS c:\> gv VAR -valueOnly
gv : Cannot find a variable with the name 'example'.
```

Environment variables, on the other hand, are meant to be global in scope.
They exist separately from the shell that created them and are available to other processes. 


## How to set an environment variable 

When setting an environment variable, you should be explicit that it is an environment variable by using the ``$Env:`` notation:

```
PS Env:/> $Env:FOO = "hello world"
PS Env:/> Get-ChildItem FOO
hello world
```

As a test, launch a new session and access the variable you've just created. 
Because the variable is an environment variable, though, you must prepend it with ``$Env``:

```
PS Env:/> pwsh
PS c:\> $Env.FOO
hello world
```

Even though you've made a variable available to child processes, it's still just a temporary variable.
It works, you can verify that it exists, you can use it from any process, but it is destroyed when the shell that created it is closed.


## Setting environment variables in your profile

To force an environment variable to persist across sessions, you must add it to your Powershell profile, such as ``CurrentUser,AllHosts`` profile, located in ``HOME/Documents/Profile.ps1``.

```
PS> Add-Content -Path $Profile.CurrentUserAllHosts -Value '$Env:FOO = "hello world"'
```

With this added, any Powershell session launched instantiates the ``FOO`` environment variable and sets its value to ``hello world``.
There are currently six default profiles controlling Powershell sessions, so refer to the [Microsoft dev blog](https://devblogs.microsoft.com/scripting/understanding-the-six-powershell-profiles) for more information.

## Discovering new environment variables

You can create and manipulate environment variables at will, and some applications do just that.
This means that many of your environment variables aren't used by most of your applications, and if you add your own arbitrary variables then some could be used by nothing at all.
So the question is: how do you find out which environment variables are meaningful?
The answer lies in an application's documentation.

Python, for instance, offers during install to add the appropriate Python path to your ``Path`` environment variable.
If you decline, you can add it yourself now that you know how to modify environment variables.
The same is true for any application you install: the installer is expected to add the appropriate variables to your environment, so you should never need to modify ``Env:`` manually.
If you're developing an application, then your installer should do the same for your users.

To discover significant variables for individual applications, refer to their user and developer documentation.