Skip to content
AgileLogics
4 min read

Script Blocks

Prerequisites: Functions

A script block — code in braces — is a value you can store, pass around, and run later. You've already used them with Where-Object and ForEach-Object.

$double = { param($x) $x * 2 }
& $double 21
$double.Invoke(5)

$operations = @{
  Add      = { param($a, $b) $a + $b }
  Multiply = { param($a, $b) $a * $b }
}
& $operations.Multiply 6 7
42
10
42
  • & (the call operator) runs a script block (or a command whose name is in a variable).
  • Script blocks can take param() like functions — they're anonymous functions.

Passing behavior to a function

function Invoke-WithRetry {
  param(
    [scriptblock]$Action,
    [int]$MaxAttempts = 3
  )
  for ($i = 1; $i -le $MaxAttempts; $i++) {
    try {
      return & $Action
    } catch {
      Write-Output "Attempt $i failed: $($_.Exception.Message)"
    }
  }
  throw "All $MaxAttempts attempts failed"
}

$script:calls = 0
Invoke-WithRetry -Action {
  $script:calls++
  if ($script:calls -lt 3) { throw 'service unavailable' }
  'Success on call 3'
}
Attempt 1 failed: service unavailable
Attempt 2 failed: service unavailable
Success on call 3

The retry logic is written once; what to retry is passed in.

Measuring time

Measure-Command { ... } runs a script block and returns how long it took — handy for comparing approaches:

# illustrative
(Measure-Command { 1..100000 | ForEach-Object { $_ } }).TotalMilliseconds
(Measure-Command { foreach ($i in 1..100000) { $i } }).TotalMilliseconds
412.8
18.3