PowerShell Environment Variables: Get, Set, and Use Them

Scripts that hard-code paths like C:\Users\john\AppData break the moment someone else runs them on their machine. PowerShell environment variables solve this by storing system and user-specific values that your scripts read at runtime. Whether you need to access $env:USERNAME, set a custom variable for a deployment pipeline, or persist a value at the machine level across reboots, PowerShell gives you multiple ways to read, write, and scope environment variables cleanly.
Read an Environment Variable with $env:
The $env: prefix is the fastest way to read any environment variable in PowerShell. Common built-in variables that are useful in scripts:
$env:USERNAME # Current user's login name
$env:COMPUTERNAME # Machine name
$env:USERPROFILE # User's home directory (C:\Users\john)
$env:APPDATA # User's AppData\Roaming
$env:TEMP # Temp folder path
$env:PATH # Semicolon-delimited executable search path
$env:WINDIR # Windows directory (usually C:\Windows)
# Use in a script to build portable paths
$logPath = "$env:USERPROFILE\Documents\Logs\script.log"
Write-Output "Logging to: $logPath"
Logging to: C:\Users\jsmith\Documents\Logs\script.log
The Env: PSDrive
Environment variables are accessible as a PSDrive called Env:. You can list all variables, iterate over them, and use the standard item cmdlets just as you would with the file system.
# List all environment variables
Get-ChildItem Env:
# List variables matching a pattern
Get-ChildItem Env: | Where-Object Name -like "APP_*"
# Access a variable via the drive
(Get-Item Env:PATH).Value
Set a Variable in Current Session
Assign to $env:VARNAME to create or update an environment variable for the current PowerShell session. This change is visible to child processes started from this session, but does not persist after the session closes.
# Create a new variable for the current session
$env:APP_ENV = "Production"
$env:APP_LOG = "C:\Logs\myapp"
# Verify it's set
Write-Output "Environment: $env:APP_ENV"
Write-Output "Log path: $env:APP_LOG"
Any process you launch from this session (including scripts, installers, or child processes) will inherit these variables automatically.
Persist at User Level
To persist an environment variable for the current user across sessions and reboots, use the .NET [System.Environment]::SetEnvironmentVariable() method with the User scope. The change takes effect in new sessions — not the current one unless you also set $env:.
# Persist at User scope
[System.Environment]::SetEnvironmentVariable("APP_ENV", "Production", "User")
# Verify stored value
[System.Environment]::GetEnvironmentVariable("APP_ENV", "User")
User-scoped variables are stored in the registry at HKCU:\Environment.
Persist at Machine Level
Machine-level environment variables apply to all users and all processes on the system. Setting them requires administrator rights. They are stored at HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment.
# Persist at Machine scope — requires admin
[System.Environment]::SetEnvironmentVariable("JAVA_HOME", "C:\Program Files\Java\jdk-21", "Machine")
# Remove a machine-level variable
[System.Environment]::SetEnvironmentVariable("OLD_VAR", $null, "Machine")
Pass $null as the value to delete a variable from the specified scope.
Expand Variables in Paths
Some paths stored in the registry or configuration files use the %VARIABLE% syntax (CMD-style). Use [System.Environment]::ExpandEnvironmentVariables() to expand them in PowerShell.
$rawPath = "%APPDATA%\Microsoft\Windows\Start Menu"
$expanded = [System.Environment]::ExpandEnvironmentVariables($rawPath)
Write-Output $expanded
C:\Users\jsmith\AppData\Roaming\Microsoft\Windows\Start Menu
# Also works with $env: variables in double-quoted strings
$configDir = "$env:APPDATA\MyApp\Config"
Common Errors and Fixes
- $env: changes are session-only: Assigning
$env:MY_VAR = "value"changes the variable for the current session only. If you need it in future sessions or for other users, call[System.Environment]::SetEnvironmentVariable()with the appropriate scope. This is the most common mistake when setting environment variables for build pipelines or startup scripts. - Machine scope requires admin rights: Calling
SetEnvironmentVariablewith"Machine"scope from a non-elevated session throws an “Access to the registry key is denied” error. Run your script as administrator or useStart-Process pwsh -Verb RunAs -ArgumentList "-Command ..."to launch an elevated process for just that step.
Related Cmdlets / See Also
Wrapping Up
Use $env: for reading, $env:VAR = "value" for session-scoped writes, and [System.Environment]::SetEnvironmentVariable() for persistence. As a next step, audit your existing scripts for hard-coded paths and replace them with $env:USERPROFILE, $env:APPDATA, or custom variables — you’ll eliminate a whole class of “works on my machine” bugs instantly.


