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.
After reading this, I went to the PowerShell help and found how to do it.
Per “get-help about_scope”, we need to use the $private:var scope:
function print-locals
{
“$localvar1”
“$localvar2”
}
function local-vars()
{
$private:localvar1 = “Hello”
$private:localvar2 = “World”
Print-locals
}
local-vars
print-locals
Specifically declaring the variables as “private” works. But the point is that the default state is neither global nor private nor local. “local” should work, by any definition of local, but it doesn’t.
It is counter-intuitive and that was what I wanted to point out.
Thanks for looking!
Alex