Skip to content

Script Blocks and Scoping Rules

Script blocks are one of the core building blocks of PowerShell. They represent executable chunks of code enclosed in {}. Scoping rules determine where variables live and which parts of a script can access them. Understanding both concepts is essential for writing predictable, maintainable scripts.


1. Script Blocks

A script block is a piece of code wrapped in curly braces:

{ "Hello" }

On its own, this does nothing until it is invoked. Script blocks are used in:

  • Functions
  • Loops
  • Pipelines (ForEach-Object, Where-Object)
  • Event handlers
  • Dynamic code execution

1.1 Executing a script block

You execute a script block using the call operator &:

$block = { "Running the block" }

& $block

Explanation:

  • $block stores the script block.
  • & $block runs the code inside it.
  • The output is: Running the block.

1.2 Script blocks with parameters

Script blocks can accept parameters using the param() keyword:

$greet = {
    param($name)
    "Hello, $name"
}

& $greet "Alice"

Explanation:

  • The script block defines a parameter $name.
  • When invoked, "Alice" is passed in.
  • Output: Hello, Alice.

1.3 Script blocks in pipelines

Script blocks are used heavily in pipeline commands.

Example with Where-Object:

1..10 | Where-Object { $_ -gt 5 }

Explanation:

  • $_ represents the current pipeline value.
  • The script block runs once per number.
  • Only numbers greater than 5 are returned.

Example with ForEach-Object:

"red","green","blue" | ForEach-Object { "Color: $_" }

Each element is processed by the script block.


2. Scoping Rules

Scope determines where a variable exists and who can see it. PowerShell has several scopes, but the most important ones for scripting are:

  • Global
  • Script
  • Local
  • Parent

Each scope controls the visibility and lifetime of variables.


2.1 Local scope

Local scope is created whenever PowerShell enters:

  • A function
  • A script block
  • A module

Variables created inside a local scope are not visible outside it.

Example:

function Test-Scope {
    $x = 10
}

Test-Scope
$x   # error: variable does not exist

Explanation:

  • $x exists only inside the function.
  • Outside the function, $x is undefined.

2.2 Script scope

Script scope applies to variables defined at the top level of a .ps1 script.

Example:

# In a script file
$script:message = "Hello"

function Show-Message {
    $script:message
}

Show-Message

Explanation:

  • $script:message is visible everywhere in the script.
  • The function can access it.

2.3 Global scope

Global scope is the top-level PowerShell session.

Variables created here are visible everywhere unless shadowed.

Example:

$global:counter = 0

function Increment {
    $global:counter++
}

Increment
$global:counter   # 1

Explanation:

  • $global:counter is shared across the entire session.
  • The function modifies the global variable.

2.4 Parent scope

A script block inherits variables from its parent scope unless overridden.

Example:

$x = 5

& {
    $x   # 5
}

The script block can see $x because it inherits from the parent scope.

If you assign a new value inside the block:

$x = 5

& {
    $x = 10
}

$x   # still 5

Explanation:

  • The assignment creates a new local $x inside the script block.
  • The outer $x remains unchanged.

To modify the parent variable explicitly:

$x = 5

& {
    $script:x = 10
}

$x   # 10

3. Script Blocks and Scope Together

3.1 Passing script blocks to functions

function Invoke-Block {
    param($block)
    & $block
}

Invoke-Block { "Inside the block" }

3.2 Script blocks capturing outer variables

$prefix = "Value:"

$block = { "$prefix 10" }

& $block

Explanation:

  • The script block uses $prefix from the parent scope.
  • Output: Value: 10.

3.3 Script blocks creating isolated scopes

& { } creates a new local scope:

$x = 1

& {
    $x = 99
}

$x   # still 1

3.4 Functions create their own scope

$x = 1

function Test {
    $x = 50
}

Test
$x   # still 1

4. When to Use Script Blocks and Scope

Scenario Use
Reusable logic Store code in a script block
Filtering or transforming pipeline data Script blocks with Where-Object or ForEach-Object
Protecting variables from accidental modification Local scope
Sharing values across a script Script scope
Sharing values across the entire session Global scope
Modifying parent variables intentionally $script: or $global: prefixes