Accessing Environment Variables in PowerShell
In a recent comment, David asked how to access environment variables in PowerShell. This is something that we normally just document explicitly: $env:Variable.
However, that explicit documentation is actually a shortcut for a feature you may not know about. It’s a little like dividing fractions – you can do it without ever knowing why it works, just that it works. Of course, it’s nice to be able to explain why.
As you may know, the ‘$’ character is the way that we access variables in PowerShell. The probing student might then ask, “Why can we access environment variables the same way we access normal variables. Isn’t ‘Env:’ the environment provider? And specific environment variables are children of it?”
Those are good questions. This is because the Environment provider shares something in common with several other providers – namely support for the *-Content set of core Cmdlets:
[C:\temp]
PS:11 > "hello world" > test
[C:\temp]
PS:12 > get-content test
hello world
[C:\temp]
PS:13 > get-content variable:ErrorActionPreference
Continue
[C:\temp]
PS:14 > get-content function:more
param([string[]]$paths); if(($paths -ne $null) -and ($paths.length -ne 0)) { ...
Get-Content $local:file | Out-Host -p } } else { $input | Out-Host ...
[C:\temp]
PS:15 > get-content env:systemroot
C:\WINDOWS
For providers that support the content cmdets, we let you interact with this content through a special variable syntax:
[C:\temp]
PS:16 > $function:more
param([string[]]$paths); if(($paths -ne $null) -and ($paths.length -ne 0)) { …
Get-Content $local:file | Out-Host -p } } else { $input | Out-Host …
[C:\temp]
PS:17 > $variable:ErrorActionPreference
Continue
[C:\temp]
PS:18 > $c:test
hello world
[C:\temp]
PS:19 > $env:systemroot
C:\WINDOWS
This variable syntax for content management allows you to both get, and set content:
[C:\temp]
PS:20> $function:more = { $input | less.exe }
[C:\temp]
PS:21> $function:more
$input | less.exe
Now, when it comes to accessing complex provider paths using this method, you’ll quickly run into naming issues:
[C:\temp]
PS:22> $c:\temp\test.txt
Unexpected token '\temp\test.txt' in expression or statement.
At line:1 char:17
+ $c:\temp\test.txt <<<<
The solution to that lies in our escaping support for complex variable names:
[C:\temp]
PS:31 > ${1234123!@#$!@#$12$!@#$@!} = "Crazy Variable!"
[C:\temp]
PS:32 > ${1234123!@#$!@#$12$!@#$@!}
Crazy Variable!
[C:\temp]
PS:33 > dir variable:\1*
Name Value
---- -----
1234123!@#$!@#$12$!@#$@! Crazy Variable!
… and the content equivalent:
[C:\temp]
PS:34 > ${c:\temp\test.txt}
hello world
So, the way to access environment variables isn’t so unique after all.