11---
22description : Explains the concept of scope in PowerShell and shows how to set and change the scope of elements.
33Locale : en-US
4- ms.date : 03/31/2023
4+ ms.date : 01/26/2024
55online version : https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_scopes?view=powershell-5.1&WT.mc_id=ps-gethelp
66schema : 2.0.0
77title : about Scopes
@@ -16,40 +16,35 @@ the scope of elements.
1616
1717PowerShell protects access to variables, aliases, functions, and PowerShell
1818drives (PSDrives) by limiting where they can be read and changed. PowerShell
19- uses scope rules to ensure that you don't inadvertently change an item that
20- shouldn't be changed.
19+ uses scope rules to ensure that you don't make unintentional changes to items
20+ in other scopes.
21+
22+ ## Scope rules
23+
24+ When you start PowerShell, the host (` pwsh.exe ` ) creates a PowerShell runspace.
25+ Host processes can have multiple runspaces. Each runspace has its own session
26+ state and scope containers. Session state and scopes can't be accessed across
27+ runspace instances.
2128
2229The following are the basic rules of scope:
2330
2431- Scopes may nest. An outer scope is referred to as a parent scope. Any nested
2532 scopes are child scopes of that parent.
26-
27- - An item is visible in the scope that it was created in and in any child
28- scopes, unless you explicitly make it private.
33+ - An item is visible in the scope that it was created and in any child scopes,
34+ unless you explicitly make it private.
2935- You can declare variables, aliases, functions, and PowerShell drives for a
3036 scope outside of the current scope.
3137- An item that you created within a scope can be changed only in the scope in
3238 which it was created, unless you explicitly specify a different scope.
33-
34- If you create an item in a scope, and the item shares its name with an item in
35- a different scope, the original item might be hidden by the new item, but it
36- isn't overridden or changed.
37-
38- ## PowerShell scopes
39-
40- PowerShell supports the following scopes:
41-
42- - ** Global** : The scope that's in effect when PowerShell starts or when you
43- create a new session or runspace. Variables and functions that are present
44- when PowerShell starts have been created in the global scope, such as
45- automatic variables and preference variables. The variables, aliases, and
46- functions in your PowerShell profiles are also created in the global scope.
47- The global scope is the root parent scope in a session.
48- - ** Local** : The current scope. The local scope can be the global scope or any
49- other scope.
50- - ** Script** : The scope that's created while a script file runs. Only the
51- commands in the script run in the script scope. To the commands in a script,
52- the script scope is the local scope.
39+ - When code running in a runspace references an item, PowerShell searches the
40+ scope hierarchy, starting with the current scope and proceeding through each
41+ parent scope. If the item isn't found, a new item is created in the current
42+ scope. If it finds a match, the value of the item is retrieved from the scope
43+ where is was found. If you change value, the item copied to the current scope
44+ so that the change only affects the current scope.
45+ - If you explicitly create an item that shares its name with an item in a
46+ different scope, the original item might be hidden by the new item, but it
47+ isn't overridden or changed.
5348
5449## Parent and child scopes
5550
@@ -58,28 +53,21 @@ scope is the parent scope. The called script or function is the child scope.
5853The functions or scripts you call may call other functions, creating a
5954hierarchy of child scopes whose root scope is the global scope.
6055
61- Unless you explicitly make the items private, the items in the parent scope
62- are available to the child scope. However, items that you create and change in
63- the child scope don't affect the parent scope, unless you explicitly specify
64- the scope when you create the items.
65-
6656> [ !NOTE]
6757> Functions from a module don't run in a child scope of the calling scope.
68- > Modules have their own session state that's linked to the global scope.
69- > All module code runs in a module-specific hierarchy of scopes that has its
70- > own root scope.
71-
72- ## Inheritance
58+ > Modules have their own session state that's linked to the scope in which the
59+ > module was imported. All module code runs in a module-specific hierarchy of
60+ > scopes that has its own root scope. For more information, see the
61+ > [ Modules] [ 02 ] section of this article.
7362
74- A child scope doesn't inherit the variables, aliases, and functions from the
75- parent scope. Unless an item is private, the child scope can view the items in
76- the parent scope. And, it can change the items by explicitly specifying the
77- parent scope, but the items aren't part of the child scope.
63+ When a child scope is created, it includes all the aliases and variables that
64+ have the ** AllScope** option, and some automatic variables. This option is
65+ discussed later in this article.
7866
79- However, a child scope is created with a set of items. Typically, it includes
80- all the aliases that have the ** AllScope ** option. This option is discussed
81- later in this article. It includes all the variables that have the ** AllScope **
82- option, plus some automatic variables .
67+ Unless you explicitly make the items private, the items in the parent scope are
68+ available to the child scope. Items that you create or change in a child scope
69+ don't affect the parent scope, unless you explicitly specify the scope when you
70+ create the items .
8371
8472To find the items in a particular scope, use the Scope parameter of
8573` Get-Variable ` or ` Get-Alias ` .
@@ -96,6 +84,36 @@ To get all the variables in the global scope, type:
9684Get-Variable -Scope global
9785```
9886
87+ When a reference is made to a variable, alias, or function, PowerShell searches
88+ the current scope. If the item isn't found, the parent scope is searched. This
89+ search is repeated all they way up to the global scope. If a variable is
90+ private in a parent scope, the search through continues through the scope
91+ chain. [ Example 4] [ 01 ] shows the the effect of a private variable in a scope
92+ search.
93+
94+ ## PowerShell scopes names
95+
96+ PowerShell defines names for some scopes to allow easier access to that scope.
97+ PowerShell defines the following named scopes:
98+
99+ - ** Global** : The scope that's in effect when PowerShell starts or when you
100+ create a new session or runspace. Variables and functions that are present
101+ when PowerShell starts, such as automatic variables and preference variables,
102+ are created in the global scope. The variables, aliases, and functions in
103+ your PowerShell profiles are also created in the global scope. The global
104+ scope is the root parent scope in a runspace.
105+ - ** Local** : The current scope. The local scope can be the global scope or any
106+ other scope.
107+ - ** Script** : The scope that's created while a script file runs. The commands
108+ in the script run in the script scope. For the commands in a script, the
109+ script scope is the local scope.
110+
111+ For cmdlets that support scopes, scopes can be referred to by a number that
112+ describes the relative position of one scope to another. Scope 0 denotes the
113+ current (local) scope, scope 1 is the current scope's parent, scope 2 is the
114+ current scope's grandparent. This pattern continues until you reach the root
115+ scope.
116+
99117## Scope modifiers
100118
101119A variable, alias, or function name can include any one of the following
@@ -108,8 +126,8 @@ optional scope modifiers:
108126 current scope.
109127
110128 > [ !NOTE]
111- > ` private ` isn't a scope. It's an [ option] [ 02 ] that changes the visibility
112- > of an item outside of the scope where the item is defined.
129+ > ` private: ` isn't a scope. It's an [ option] [ 03 ] that changes the
130+ > accessibility of an item outside of the scope in which it's defined.
113131
114132- ` script: ` - Specifies that the name exists in the ** Script** scope.
115133 ** Script** scope is the nearest ancestor script file's scope or ** Global** if
@@ -246,16 +264,16 @@ Depending on the context, embedded variable values are either independent
246264copies of the data in the caller's scope or references to it. In remote and
247265out-of-process sessions, they're always independent copies.
248266
249- For more information, see [ about_Remote_Variables] [ 06 ] .
267+ For more information, see [ about_Remote_Variables] [ 07 ] .
250268
251269In thread sessions, they're passed by reference. This means it's possible to
252270modify child scope variables in a different thread. To safely modify variables
253271requires thread synchronization.
254272
255273For more information see:
256274
257- - [ Start-ThreadJob] [ 10 ]
258- - [ ForEach-Object] [ 09 ]
275+ - [ Start-ThreadJob] [ 11 ]
276+ - [ ForEach-Object] [ 10 ]
259277
260278### Serialization of variable values
261279
@@ -367,7 +385,7 @@ Using the call operator is no different than running the script by name.
367385& c:\scripts\sample.ps1
368386```
369387
370- You can read more about the call operator in [ about_Operators] [ 05 ] .
388+ You can read more about the call operator in [ about_Operators] [ 06 ] .
371389
372390To run the ` Sample.ps1 ` script in the local scope type a dot and a space (` . ` )
373391before the path to the script:
@@ -405,28 +423,15 @@ example, you can run a script to create a child scope in a session.
405423
406424You can use a PowerShell module to share and deliver PowerShell tools. A module
407425is a unit that can contain cmdlets, scripts, functions, variables, aliases, and
408- other useful items. Unless explicitly defined, the items in a module aren't
409- accessible outside the module. Therefore, you can add the module to your
410- session and use the public items without worrying that the other items might
411- override the cmdlets, scripts, functions, and other items in your session.
412-
413- By default, modules are loaded into the top-level of the current _ session
414- state_ not the current _ scope_ . The current session state could be a module
415- session state or the global session state. Adding a module to a session does
416- not change the scope. If you are in the global scope, then modules are loaded
417- into the global session state. Any exports are placed into the global tables.
418- If you load module2 from _ within_ module1, module2 is loaded into the session
419- state of module1 not the global session state. Any exports from module2 are
420- placed at the top of the module1 session state. If you use
421- ` Import-Module -Scope local ` , then the exports are placed into the current
422- scope object rather than at the top level. If you are _ in a module_ and use
423- ` Import-Module -Scope global ` (or ` Import-Module -Global ` ) to load another
424- module, that module and its exports are loaded into the global session state
425- instead of the module's local session state. This feature was designed for
426- writing module that manipulate modules. The ** WindowsCompatibility** module
427- does this to import proxy modules into the global session state.
428-
429- Within the session state, modules have their own scope. Consider the following
426+ other useful items. Unless explicitly exported (using ` Export-ModuleMember ` or
427+ the module manifest), the items in a module aren't accessible outside the
428+ module. Therefore, you can add the module to your session and use the public
429+ items without worrying that the other items might override the cmdlets,
430+ scripts, functions, and other items in your session.
431+
432+ By default, modules are loaded into the root-level (global) scope of the
433+ runspace. Importing a module doesn't change the scope.
434+ Within the session, modules have their own scope. Consider the following
430435module ` C:\temp\mod1.psm1 ` :
431436
432437``` powershell
@@ -454,6 +459,23 @@ $a = Hello
454459$global:a = Goodbye
455460```
456461
462+ Modules create parallel scope containers linked to the scope in which they were
463+ imported. Items exported by the module are available starting at the
464+ scope-level in which they are imported. Items not exported from the module are
465+ only available within the module's scope container. Functions in the module can
466+ access items in the scope in which they were imported as well as items in the
467+ module's scope container.
468+
469+ If you load ** Module2** from _ within_ ** Module1** , ** Module2** is loaded into
470+ the scope container of Module1. Any exports from ** Module2** are placed in the
471+ current module scope of ** Module1** . If you use ` Import-Module -Scope local ` ,
472+ then the exports are placed into the current scope object rather than at the
473+ top level. If you are _ in a module_ and load another module using
474+ ` Import-Module -Scope global ` (or ` Import-Module -Global ` ), that module and its
475+ exports are loaded into the global scope instead of the module's local scope.
476+ The ** WindowsCompatibility** feature does this to import proxy modules into the
477+ global session state.
478+
457479### Nested prompts
458480
459481Nested prompts don't have their own scope. When you enter a nested prompt, the
@@ -612,44 +634,81 @@ Local
612634
613635### Example 4: Creating a private variable
614636
615- A private variable is a variable that has an ** Option** property that has a
616- value of ` Private ` . ` Private ` variables are inherited by the child scope, but
617- they can only be viewed or changed in the scope in which they were created.
637+ A variable can be made private by using the ` private: ` scope modifier or by
638+ creating the variable with the ** Option** property set to ` Private ` . Private
639+ variables can only be viewed or changed in the scope in which they were
640+ created.
618641
619- The following command creates a private variable called ` $ptest ` in the local
620- scope.
642+ In this example, the ` ScopeExample.ps1 ` script creates five functions. The
643+ first function calls the next function, which creates a child scope. One of the
644+ functions has a private variable that can only be seen in the scope in which it
645+ was created.
621646
622647``` powershell
623- New-Variable -Name ptest -Value 1 -Option Private
624- ```
625-
626- You can display and change the value of ` $ptest ` in the local scope.
627-
628- ```
629- PS> $ptest
630- 1
648+ PS> Get-Content ScopeExample.ps1
649+ # Start of ScopeExample.ps1
650+ function funcA {
651+ "Setting `$funcAVar1 to 'Value set in funcA'"
652+ $funcAVar1 = "Value set in funcA"
653+ funcB
654+ }
631655
632- PS> $ptest = 2
633- PS> $ptest
634- 2
635- ```
656+ function funcB {
657+ "In funcB before set -> '$funcAVar1'"
658+ $private:funcAVar1 = "Locally overwrite the value - child scopes can't see me!"
659+ "In funcB after set -> '$funcAVar1'"
660+ funcC
661+ }
636662
637- Next, create a Sample.ps1 script that contains the following commands. The
638- command tries to display and change the value of ` $ptest ` .
663+ function funcC {
664+ "In funcC before set -> '$funcAVar1' - should be the value set in funcA"
665+ $funcAVar1 = "Value set in funcC - Child scopes can see this change."
666+ "In funcC after set -> '$funcAVar1'"
667+ funcD
668+ }
639669
640- In Sample.ps1:
670+ function funcD {
671+ "In funcD before set -> '$funcAVar1' - should be the value from funcC."
672+ $funcAVar1 = "Value set in funcD"
673+ "In funcD after set -> '$funcAVar1'"
674+ '-------------------'
675+ ShowScopes
676+ }
641677
642- ``` powershell
643- "The value of `$Ptest is $Ptest."
644- "The value of `$Ptest is $global:Ptest."
678+ function ShowScopes {
679+ $funcAVar1 = "Value set in ShowScopes"
680+ "Scope [0] (local) `$funcAVar1 = '$(Get-Variable funcAVar1 -Scope 0 -ValueOnly)'"
681+ "Scope [1] (parent) `$funcAVar1 = '$(Get-Variable funcAVar1 -Scope 1 -ValueOnly)'"
682+ "Scope [2] (parent) `$funcAVar1 = '$(Get-Variable funcAVar1 -Scope 2 -ValueOnly)'"
683+ "Scope [3] (parent) `$funcAVar1 = '$(Get-Variable funcAVar1 -Scope 3 -ValueOnly)'"
684+ "Scope [4] (parent) `$funcAVar1 = '$(Get-Variable funcAVar1 -Scope 4 -ValueOnly)'"
685+ }
686+ funcA
687+ # End of ScopeExample.ps1
688+ PS> .\ScopeExample.ps1
645689```
646690
647- The ` $ptest ` variable isn't visible in the script scope, the output is empty.
691+ The output shows the value of the variable in each scope. You can see that the
692+ private variable is only visible in ` funcB ` , the scope in which it was created.
648693
649- ``` powershell
650- "The value of $Ptest is ."
651- "The value of $Ptest is ."
652- ```
694+ ``` Output
695+ Setting $funcAVar1 to 'Value set in funcA'
696+ In funcB before set -> 'Value set in funcA'
697+ In funcB after set -> 'Locally overwrite the value - child scopes can't see me!'
698+ In funcC before set -> 'Value set in funcA' - should be the value set in funcA
699+ In funcC after set -> 'Value set in funcC - Child scopes can see this change.'
700+ In funcD before set -> 'Value set in funcC - Child scopes can see this change.' - should be the value from funcC.
701+ In funcD after set -> 'Value set in funcD'
702+ -------------------
703+ Scope [0] (local) $funcAVar1 = 'Value set in ShowScopes'
704+ Scope [1] (parent) $funcAVar1 = 'Value set in funcD'
705+ Scope [2] (parent) $funcAVar1 = 'Value set in funcC - Child scopes can see this change.'
706+ Scope [3] (parent) $funcAVar1 = 'Locally overwrite the value - child scopes can't see me!'
707+ Scope [4] (parent) $funcAVar1 = 'Value set in funcA'
708+ ```
709+
710+ As shown by the output from ` ShowScopes ` , you can access variables from other
711+ scopes using ` Get-Variable ` and specifying a scope number.
653712
654713### Example 5: Using a local variable in a remote command
655714
@@ -675,19 +734,21 @@ The `using` scope modifier was introduced in PowerShell 3.0.
675734
676735## See also
677736
678- - [ about_Variables] [ 08 ]
679- - [ about_Environment_Variables] [ 03 ]
680- - [ about_Functions] [ 04 ]
681- - [ about_Script_Blocks] [ 07 ]
682- - [ Start-ThreadJob] [ 10 ]
737+ - [ about_Variables] [ 09 ]
738+ - [ about_Environment_Variables] [ 04 ]
739+ - [ about_Functions] [ 05 ]
740+ - [ about_Script_Blocks] [ 08 ]
741+ - [ Start-ThreadJob] [ 11 ]
683742
684743<!-- link references -->
685- [ 02 ] : #private-option
686- [ 03 ] : about_Environment_Variables.md
687- [ 04 ] : about_Functions.md
688- [ 05 ] : about_Operators.md
689- [ 06 ] : about_Remote_Variables.md
690- [ 07 ] : about_Script_Blocks.md
691- [ 08 ] : about_Variables.md
692- [ 09 ] : xref:Microsoft.PowerShell.Core.ForEach-Object
693- [ 10 ] : xref:ThreadJob.Start-ThreadJob
744+ [ 01 ] : #example-4-creating-a-private-variable
745+ [ 02 ] : #modules
746+ [ 03 ] : #private-option
747+ [ 04 ] : about_Environment_Variables.md
748+ [ 05 ] : about_Functions.md
749+ [ 06 ] : about_Operators.md
750+ [ 07 ] : about_Remote_Variables.md
751+ [ 08 ] : about_Script_Blocks.md
752+ [ 09 ] : about_Variables.md
753+ [ 10 ] : xref:Microsoft.PowerShell.Core.ForEach-Object
754+ [ 11 ] : xref:ThreadJob.Start-ThreadJob
0 commit comments