Tags


I don’t know about you, but I dislike having to memorise something simply because “that’s the way it is”. I like to understand WHY. That makes it easier to learn. A PowerShell example is the common syntax for accessing Environment variables, eg:

$windows = $env:windir

OK, I understand what that does but not HOW that syntax gets that end result.

Now, this form of syntax I DO understand:

$windows = Get-Item "env:Windir" | Select-Object -ExpandProperty Value

or

$windows = (Get-Item "env:Windir").Value

Though unwieldy, at least those make sense as your’re accessing an item in the env: PSDrive and then getting its Value – since the items in the env: drive are returned as Dictionary entries:

(Get-Item "env:Windir").GetType().FullName

(Returns “System.Collections.DictionaryEntry”).

So what about $env:Windir?
After talking with “Palmar” in the PowerShell livechat, it occurred to me to think of a similar syntax involving variables – scope.

You can reference a variable outside the current scope of execution by using the syntax:

$<Scope>:<VariableName>

such as

$Script:VariableName

or

$Global:VariableName

This sort of thing is frowned upon – you should pass parameters into functions rather than access them at the parent level directly. It makes debugging much easier.

So you could sort of think of $env:variable as referring to an Environment Scope. You won’t find any mention of that in help topic “about_scope” though.

The help topic “about_environment_variables” has this to say on the subject:

In this syntax, the dollar sign ($) indicates a variable, and the drive name indicates an environment variable.

My next thought was to try it with a different drive that holds variables. The following, though entirely redundant, does indeed work:

$versions = $variable:PSVersionTable

So there you have it. The syntax can be thought of as:

$<PSDrive-That-Holds-Variables>:<Variable-Name>

Since “PSDrive-That-Holds-Variables” means the env: drive or the variable: drive, and since the “$variable:” syntax is redundant, that just leaves us with “$env:” !


There’s an extension to this discussion.
I’ve also seen this syntax with curly braces:

$pf86 = ${env:ProgramFiles(x86)}

This is because the variable name contains parentheses which would be an illegal character. Taking env: out of the equation, you may have seen mention of creating variable names with spaces in. There, the name but not the dollar sign has to be wrapped in braces such as:

${My Stupid Variable Name} = "Hello World"

So the env: example above is just a natural extension of this.



Update:
As you’ll see from Joel’s comments below, there is a bit more to this than had met my eye.
The upshot of it is that this syntax works for any PSDrive that supports Get-Content and is known as Variable Namespace Notation or Variable Syntax for Content Management.

Advertisements