Remarks:
* This answer explains why OP code behaves the way it works (and that it behaves as intended); in addition, it provides some general information about variable areas in PowerShell.
* For an important real use of scope in private see PetSerAl's helpful answer .
Your first piece of code:
variable a contains variable a contains 2
Your second print of the fragment:
variable a contains 1 variable a contains 2
In the first fragment, the codes, using a set of private reasons of the parent (script), the sphere a variable to be hidden from the childβs sphere (function), as intended, so the first line of the output shows that $a does not matter
(an undefined variable has a value of $null , which evaluates to an empty string in a string context).
In the second fragment, on the contrary, without the private scope modifier, the variable a from the parent scope is visible to the child scope.
In PowerShell, functions are by default executed in child areas.
Thus, in both of the above fragments, assigning the variable a inside the function implicitly creates a local a variable there, whose volume is limited by the containing function.
In other words:
- Assigning
$a to a function creates a local variable of the function called $a , which then hides (hides) the $a script level variable (if it has not already been hidden, being declared as $private:a ) - When exiting the function,
$a again has its initial script level value.
Understanding Variable Areas in PowerShell
If the variable is not explicitly hidden in the private scope, private regions can see this variable and read its value using the variable name without the scope qualifier (for example, $a ) or the need for Get-Variable -Scope .
- Other areas not only do not see the values ββof private variables by default, but basically cannot refer to them, even with explicit -Scope cross-access using scope modifiers or
Get-Variable -Scope .
(However, in the same scope, you can use the scope modifier to refer to a private variable, but only if this scope modifier effectively targets the same scope, which is always true for $local:privateVarName , $local:privateVarName ).
Assigning an unqualified variable, however, implicitly creates a new variable in the current ( local ) region , which can hide a variable with the same name in the ancestral region.
- That is,
$a = 2 implicitly matches $local:a = 2 .
To explicitly get / change a variable in the hereditary region, use Get-Variable/Set-Variable -Scope <n> <name> , where <n> represents the level of the region, where 0 represents the current region, 1 parent region, and so on.
Note that Get-Variable returns an instance of [System.Management.Automation.PSVariable] by default, so to get only the value, access its .Value property or use the -ValueOnly switch, which returns the value just to start with.
In functions and interrupt handlers, before creating a local copy of a variable, you can alternatively change the variable in the immediate area of ββthe ancestors, where it is defined as follows:
([ref] $var).Value =...- (If one day a local variable with the same name is created, the above will only change the local variable.)
Variables in the scope of the script and in the global scope can also be accessed and modified using the $script: and $global: scope modifiers ; e.g. $script:a and $global:a .
Note that $script: refers to (directly) the top-level area of ββthe script file.
Declaring a variable using Set-Variable -Option AllScope allows you to read and modify it in any descendant region without the need for a Set-Variable -Option AllScope name ; in other words: then there is only one variable with that name that any area can directly read and write using the unqualified name of the variable.
Without a separate -Scope parameter, -Option AllScope is applied to the variable in the current area (for example, the script area at the top level of the script, the local scope function inside the function). Thus, to safely create a global script variable that can be accessed by unqualified readers and writers, use Set-Variable -Scope Script -Option AllScope .
-Scope Global is different from -Option AllScope : while -Scope Global creates a globally accessible variable, the $global: scope modifier is required to read and modify it. Also note that the global variable is a session global , so it is saved even after the script that defined it is complete.
By combining -Scope Global with -Option AllScope you effectively create a global singleton session variable that can be read and written from any area without a specifier; as already mentioned, such a variable remains valid even after exiting your script.
source share