PowerShell Genie

PowerShell Scope

PowerShell scopes are nested. A function can read variables from the scope that called it, but assigning to one creates a new local variable instead of changing the original.

Lesson 2 min read Windows PowerShell 5.1 and PowerShell 7

Documentation: Microsoft Learn

Overview

That asymmetry is the whole lesson. Reading looks like it shares state, so people assume writing does too. It does not: the assignment shadows the outer variable for the rest of the function, and the caller's value is untouched.

Scope modifiers exist for the cases where you really do want to reach out. $script:total refers to the variable at script level, $global:config to the global one. Both work, and both make code harder to follow, so treat them as a last resort. Passing a value in as a parameter and returning the result is almost always clearer.

Dot-sourcing changes the rules. Running . .\script.ps1 with a leading dot and space executes the file in your current scope, so its functions and variables stay behind after it finishes. That is how profile scripts and module-style helper files load.

Inspect this example’s structure

Read the command and its supplied arguments. This example requires real PowerShell or its module; this diagram does not execute it.

$counter = 10 function Test-Scope { Write-Output "Function sees: $counter" $counter = 99 Write-Output "Function set it to: $counter" } Test-Scope Write-Output "Caller still has: $counter"
  1. Stage 1$counterPositional values or no named parameters

    An example to inspect

    Preview the example. Sign in for the full lesson and activities.

    $counter = 10
    function Test-Scope {
    Write-Output "Function sees: $counter"
    $counter = 99
    Write-Output "Function set it to: $counter"
    }
    Test-Scope
    Write-Output "Caller still has: $counter"

    What happens

    $counter is 10 at script level. The function reads it and prints 10, which shows reading crosses the boundary. It then assigns 99 and prints 99, which is the new local variable. After the function returns, the caller still sees 10, because the outer variable was never touched.

    Worth remembering

    • A function can read the caller's variables.
    • Assigning creates a local copy. The original is unchanged.
    • $script: and $global: reach outward, at the cost of clarity.
    • Dot-sourcing with '. .\file.ps1' runs the file in the current scope.

    Primary documentation

    PowerShell objects and pipelines documentation

    Try it

    Illustrative output · values vary by environment

    1PS> $counter = 10
    2PS> function Test-Scope {
    3PS> Write-Output "Function sees: $counter"
    4PS> $counter = 99
    5PS> Write-Output "Function set it to: $counter"
    6PS> }
    7PS> Test-Scope
    8PS> Write-Output "Caller still has: $counter"

    Example reader

    Inspect this page's example

    Fictional browser data when supported

    Run supported commands against the practice data, or inspect the example without executing it.

    Ready to inspect.

      Show reference output
      Function sees: 10
      Function set it to: 99
      Caller still has: 10

      Shows that a function reads outer variables but cannot assign to them.

      Practise this

      Store reusable function output

      Define Get-ServiceSummary returning Name and Status, then store its output in $summary.

      Review the lesson

      Keep going

      Next: PowerShell Parameters and validation
      Genie guidePowerShell Scope

      PowerShell scopes are nested. A function can read variables from the scope that called it, but assigning to one creates a new local variable instead of changing the original.