PowerShell and Schrödinger’s cat

Powershell does not require you to declare variables. For a shell, that makes perfect sense because that would create too much overhead for simple one-off tasks.

However, as soon as you start to develop more complex scripts, it is very important to know what scope your dynamically created variables have. Consider the following VBScript:

Function Printlocals
    WScript.Echo LocalVar1
    WScript.Echo LocalVar2
End Function

Function Localvariables
    LocalVar1 = "Hello"
    LocalVar2 = "World"
    Printlocals
End Function

Localvariables
printlocals

The output of this script is absolutely nothing, except for some empty lines. Because the variables LocalVar1 and LocalVar2 are always empty in the context of the function Printlocals

No big surprise here. So let’s do the same thing in PowerShell

function print-locals
{
    "$localvar1"
    "$localvar2"
}

function local-vars()
{
    $localvar1 = "Hello"
    $localvar2 = "World"
    Print-locals
}

local-vars
print-locals

What we get as output here is the following:

Hello
World

This output comes from the first call to Print-Locals after setting their value inside Local-Vars. The variables are empty again when you call Print-locals again from any other context.

It is important to note that the result is the same if you use the $local:localvar1 notation.

So the scope of those variables is neither global nor local in the traditional sense. One could now assume that you cannot know what the content or scope of a variable is until you try to access it, just like the state of the cat in Schrödinger’s thought experiment.

Judging from this experiment it appears that local scope variables in PowerShell are of "downstream" scope, meaning that they are accessible to anything that is called afterwards, but go out of scope once the code returns from the context in which they are created.

This is an important difference to other scripting languages and can make for some interesting debugging sessions should you forget about this.