Variable scoping in PowerShell Variable scoping in PowerShell powershell powershell

Variable scoping in PowerShell


The PowerShell scopes article (about_Scopes) is nice, but too verbose, so this is quotation from my article:

In general, PowerShell scopes are like .NET scopes. They are:

  • Global is public
  • Script is internal
  • Private is private
  • Local is current stack level
  • Numbered scopes are from 0..N where each step is up to stack level (and 0 is Local)

Here is simple example, which describes usage and effects of scopes:

$test = 'Global Scope'Function Foo {    $test = 'Function Scope'    Write-Host $Global:test                                  # Global Scope    Write-Host $Local:test                                   # Function Scope    Write-Host $test                                         # Function Scope    Write-Host (Get-Variable -Name test -ValueOnly -Scope 0) # Function Scope    Write-Host (Get-Variable -Name test -ValueOnly -Scope 1) # Global Scope}Foo

As you can see, you can use $Global:test like syntax only with named scopes, $0:test will be always $null.


You can use scope modifiers or the *-Variable cmdlets.

The scope modifiers are:

  • global used to access/modify at the outermost scope (eg. the interactive shell)
  • script used on access/modify at the scope of the running script (.ps1 file). If not running a script then operates as global.

(For the -Scope parameter of the *-Variable cmdlets see the help.)

Eg. in your second example, to directly modify the global $array:

& {  $global:array +="s"  Write-Host $array}

For more details see the help topic about_scopes.


Not just varibles. When this says "item" it means variables, functions, aliases, and psdrives. All of those have scope.

LONG DESCRIPTION      Windows PowerShell protects access to variables, aliases, functions, and    Windows PowerShell drives (PSDrives) by limiting where they can be read and    changed. By enforcing a few simple rules for scope, Windows PowerShell    helps to ensure that you do not inadvertently change an item that should    not be changed.    The following are the basic rules of scope:        - An item you include in a scope is visible in the scope in which it          was created and in any child scope, unless you explicitly make it          private. You can place variables, aliases, functions, or Windows          PowerShell drives in one or more scopes.        - An item that you created within a scope can be changed only in the          scope in which it was created, unless you explicitly specify a          different scope.

The copy on write issue you're seeing is because of the way Powershell handles arrays. Adding to that array actually destroys the original array and creates a new one. Since it was created in that scope, it is destroyed when the function or script block exits and the scope is disposed of.

You can explicitly scope varibles when you update them, or you can use [ref] objects to do your updates, or write your script so that you're updating a property of an object or a hash table key of an object or hash table in a parent scope. This does not create a new object in the local scope, it modifies the object in the parent scope.