If I declare and initialize a PowerShell variable with $global:MyVariable = "123"
do I then need to use $global: anywhere I use the variable or can I just use $MyVariable?

- 2,413
- 3
- 26
- 34
-
2get-help about_scope – Kory Gill Jan 22 '19 at 21:06
3 Answers
In principle you can use just
$MyVariable
to reference the value of a global variable by that name, but you may see a different variable's value, situationally.Specifically, if any intervening ancestral (parent) scope or even the calling scope itself has also created a
$MyVariable
variable (which typically happens implicitly by simple assigmnent; e.g.,$MyVariable = ...
), you will see that variable's value instead.You're only guaranteed to see the global value if you do use the global scope specifier, namely:
$global:MyVariable
(orGet-Variable -ValueOnly -Scope Global MyVariable
)[1]By default, variables are visible, but not directly modifiable in all descendant (child) scopes.
- Therefore you must use
$global:MyVariable
/Set-Variable -Scope Global
in order to modify (set) a global variable; without$global:
you'll implicitly create a local variable by the same name. - For more on PowerShell's scoping rules, see the last section of this answer.
- Therefore you must use
[1] In real-world scenarios, even code in PowerShell modules sees global variables with scope specifier $global:
, and the implicit visibility of global variables always applies.
For in-memory modules, there is a way to make $global
/ -Scope global
refer to a different scope, namely the module's own top-level scope, but the technique is obscure, not documented, and its real-world utility is unknown.
Read on, if you want to know more.
Optional reading: Creating an in-memory module that sees its own top-level scope as the global scope:
PetSerAl has discovered a little-known way to create an in-memory module in a manner that makes it see $global:
/ -Scope global
as its own top-level scope rather than the true global scope - curiously, not using an explicit scope reference makes the code still see (non-shadowed) global variables:
$global:MyVariable = 42 # Create a true global variable.
# Create an in-memory module for which its *own top-level scope*
# becomes the "global" scope, by virtue of passing $false to the
# [psmoduleinfo] constructor:
& ([psmoduleinfo]::new($false)) {
@"
"$global:MyVariable",
"$(Get-Variable -ValueOnly -Scope global MyVariable)",
"$MyVariable"
"@
}
yields:
Get-Variable : Cannot find a variable with the name 'MyVariable'.
# ...
"", # $global:MyVariable didn't find the variable
", # Neither did Get-Variable -Scope Global (see error above)
"42" # OK - implicit visibility of true global variables
Note that neither New-Module
nor Import-Module
(for persisted modules) offer this functionality.
The obscure & <module-info> { ... }
technique used above for invoking a script block in a module's scope is explained in this excellent blog post by Patrick Meinecke.

- 382,024
- 64
- 607
- 775
-
1You could also access true global variables by using right numbered scope: https://tio.run/##K8gvTy0qzkjNyfn/XyU9Jz8pMcfKtzIssSgzMSknVcFWwcSIS01BI7qgODc/pTQnNTMvLT/WyiovtVxDJS0xpzhVU1OhWsE9tUQXrgfIyilN9c/LqVTQDU7OL0hVMFLQ9UvMTVVAMrj2/38A – user4003407 Jan 23 '19 at 22:40
-
1This in memory module idea is very interesting. I would be very nervous about using that and having to explain it so other developers who might need to work on the code. However, it's good to know about edge cases like this for when it's truly needed. – Matthew MacFarland Jan 25 '19 at 15:41
Run this and see that it is best to always specify, if you don't you will not alwys get what you might expect
function func {
"0. $myvar"
$myvar='funclocal'
"1. $myvar"
"2. $Global:myvar"
}
$Global:myvar='global'
func
"3. $Global:myvar"

- 1,138
- 7
- 10
-
1_"best to always specify"_ -- I wouldn't go so far. It entirely depends on your use case. It's very common to have a global setting, that you want to override locally only for the scope of the current function. A good example is `$ErrorActionPreference`. If a local function wants to override this setting, it will just use the variable without `Global` prefix, so the global `$ErrorActionPreference` won't be affected. – zett42 Jan 22 '19 at 21:37
-
@zett42 Agree. But in that case you consciously play the global-local game. What I meant is that you should not leave it to the situation which variable is used, Especially in bigger scripts/modules it potentially gives you headaches. It also makes scripts clearer to read for others when global vars are prefixed IMHO. So yes, it is optional. But think about where and why. – Gert Jan Kraaijeveld Jan 23 '19 at 06:27
-
In the solution I am working on I think the presence of the $global: qualifier will add a lot to the readability of the code. Some of the references are going to be a little verbose because the variable is a hash table with some nested keys but I think that is the lesser concern. – Matthew MacFarland Jan 25 '19 at 16:07
you do not need to use $global: when calling

- 137
- 1
- 11
-
You're technically correct, but there are certainly caveats. Perhaps the down-votes stem from others feeling that these caveats should be elaborated on. – mklement0 Jan 24 '19 at 01:13
-