I'm surprised that I didn't get the answer for this common scenario after Googling for while...
How can an environment variable in be set in PowerShell if it does not exist?
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.
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. Environment variables convey information about your login session to your computer.
To refresh the environment variables in PowerShell, retrieves the environment variables and assign them $Env:Path to reload the environment variable path in the PowerShell. After reloading the path in PowerShell, you don't need to restart the PowerShell ISE or terminal.
The following code defines environment variable FOO
for the current process, if it doesn't exist yet.
if ($null -eq $env:FOO) { $env:FOO = 'bar' } # Alternatively: if (-not (Test-Path env:FOO)) { $env:FOO = 'bar' }
In PowerShell (Core) 7.1+, which has null-coalescing operators, you can simplify to:
$env:FOO ??= 'bar'
Note: Environment variables are strings by definition. If a given environment variable is defined, but has no value, its value is the empty string (''
) rather than $null
. Thus, comparing to $null
can be used to distinguish between an undefined environment variable and one that is defined, but has no value. However, note that assigning to environment variables in PowerShell / .NET makes no distinction between $null
and ''
, and either value results in undefining (removing) the target environment variable.
Note: If the environment variable is created on demand by the assignment above ($env:FOO = ...
), it will exist for the current process and any child processes it creates only Thanks, PetSerAl.
The following was mostly contributed by Ansgar Wiechers, with a supplement by Mathias R. Jessen:
On Windows[*], if you want to define an environment variable persistently, you need to use the static SetEnvironmentVariable()
method of the [System.Environment]
class:
# user environment [Environment]::SetEnvironmentVariable('FOO', 'bar', 'User') # system environment (requires admin privileges) [Environment]::SetEnvironmentVariable('FOO', 'bar', 'Machine')
Note that these definitions take effect in future sessions (processes), so in order to define the variable for the current process as well, run $env:FOO = 'bar'
in addition, which is effectively the same as [Environment]::SetEnvironmentVariable('FOO', 'bar', 'Process')
.
When using [Environment]::SetEnvironmentVariable()
with User
or Machine
, a WM_SETTINGCHANGE
message is sent to other applications to notify them of the change (though few applications react to such notifications).
This doesn't apply when targeting Process
(or when assigning to $env:FOO
), because no other applications (processes) can see the variable anyway.
See also.
[*] On Unix-like platforms, attempts to target persistent scopes User
or Machine
are quietly ignored, as of .NET (Core) 5, and this non-support for defining persistent environment variables is unlikely to change, given the lack of a unified mechanism across Unix platforms.
Code
function Set-LocalEnvironmentVariable { param ( [Parameter()] [System.String] $Name, [Parameter()] [System.String] $Value, [Parameter()] [Switch] $Append ) if($Append.IsPresent) { if(Test-Path "env:$Name") { $Value = (Get-Item "env:$Name").Value + $Value } } Set-Item env:$Name -Value "$value" | Out-Null } function Set-PersistentEnvironmentVariable { param ( [Parameter()] [System.String] $Name, [Parameter()] [System.String] $Value, [Parameter()] [Switch] $Append ) Set-LocalEnvironmentVariable -Name $Name -Value $Value -Append:$Append if ($Append.IsPresent) { $value = (Get-Item "env:$Name").Value } if ($IsWindows) { setx "$Name" "$Value" | Out-Null return } $pattern = "\s*export[ \t]+$Name=[\w]*[ \t]*>[ \t]*\/dev\/null[ \t]*;[ \t]*#[ \t]*$Name\s*" if ($IsLinux) { $file = "~/.bash_profile" $content = (Get-Content "$file" -ErrorAction Ignore -Raw) + [System.String]::Empty $content = [System.Text.RegularExpressions.Regex]::Replace($content, $pattern, [String]::Empty); $content += [System.Environment]::NewLine + [System.Environment]::NewLine + "export $Name=$Value > /dev/null ; # $Name" Set-Content "$file" -Value $content -Force return } if ($IsMacOS) { $file = "~/.zprofile" $content = (Get-Content "$file" -ErrorAction Ignore -Raw) + [System.String]::Empty $content = [System.Text.RegularExpressions.Regex]::Replace($content, $pattern, [String]::Empty); $content += [System.Environment]::NewLine + [System.Environment]::NewLine + "export $Name=$Value > /dev/null ; # $Name" Set-Content "$file" -Value $content -Force return } throw "Invalid platform." }
On Windows you can use:
On Linux we can add export VARIABLE_NAME=Variable value to file ~/.bash_profile. For a new bash terminal the process execute these instructions located in ~/.bash_profile.
On MacOS similiar to Linux but if you have zsh terminal the file is .zprofile, if the default terminal is bash, the file is .bash_profile. In my function code we need to add detection of default terminal if you wish. I assume that default terminal is zsh.
Examples
#Set "Jo" value to variable "NameX", this value is accesible in current process and subprocesses, this value is accessible in new opened terminal. Set-PersistentEnvironmentVariable -Name "NameX" -Value "Jo"; Write-Host $env:NameX #Append value "ma" to current value of variable "NameX", this value is accesible in current process and subprocesses, this value is accessible in new opened terminal. Set-PersistentEnvironmentVariable -Name "NameX" -Value "ma" -Append; Write-Host $env:NameX #Set ".JomaProfile" value to variable "ProfileX", this value is accesible in current process/subprocess. Set-LocalEnvironmentVariable "ProfileX" ".JomaProfile"; Write-Host $env:ProfileX
Output
Windows 10
Ubuntu WSL
References
Check About Environment Variables
Shell initialization files
ZSH: .zprofile, .zshrc, .zlogin - What goes where?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With