I want to write a function that accepts a scriptblock as a parameter and executes that scriptblock in the scope in which it was invoked.
The Measure-Command is an example of the behavior I would like. The scriptblock runs in with the same scope as the Measure-Command itself. If the scriptblock references a variable in this scope, the script can change it.
Attached is a sample scriptblock that increments the $a variable. When invoked by Measure-Command, the variable is incremented. But when invoked by the Wrapper functions, the variable will not increment -- unless I dot-source both the invocation of the Wrapper function and the Wrapper function itself uses dot-sourcing.
function Wrapper1
{
param( $scriptBlock )
$startTime = Get-Date
Write-Output ( "{0:HH:mm:ss} Start script" -f $startTime )
& $scriptBlock
$endTime = Get-Date
Write-Output ( "{0:HH:mm:ss} End script - {1:c} seconds elapsed" -f $endTime, ( $endTime - $StartTime ) )
}
function Wrapper2
{
param( $scriptBlock )
$startTime = Get-Date
Write-Output ( "{0:HH:mm:ss} Start script" -f $startTime )
. $scriptBlock
$endTime = Get-Date
Write-Output ( "{0:HH:mm:ss} End script - {1:c} seconds elapsed" -f $endTime, ( $endTime - $StartTime ) )
}
$a = 1
Write-Output "Initial state: `$a = $a"
Measure-Command { $a++ } | Out-Null
Write-Output "Measure-Command results: `$a = $a"
Wrapper1 { $a++ }
Write-Output "Wrapper1 results: `$a = $a"
. Wrapper1 { $a++ }
Write-Output "dot-sourced Wrapper1 results: `$a = $a"
Wrapper2 { $a++ }
Write-Output "Wrapper2 results: `$a = $a"
. Wrapper2 { $a++ }
Write-Output "dot-sourced Wrapper2 results: `$a = $a"
The result of running this code is:
Initial state: $a = 1
Measure-Command results: $a = 2
13:44:49 Start script
13:44:49 End script - 00:00:00 seconds elapsed
Wrapper1 results: $a = 2
13:44:49 Start script
13:44:49 End script - 00:00:00.0157407 seconds elapsed
dot-sourced Wrapper1 results: $a = 2
13:44:49 Start script
13:44:49 End script - 00:00:00 seconds elapsed
Wrapper2 results: $a = 2
13:44:49 Start script
13:44:49 End script - 00:00:00 seconds elapsed
dot-sourced Wrapper2 results: $a = 3
Although this last option works, I'd like to avoid the dot-source syntax invoking Wrapper2. Is this possible? The Measure-Command doesn't use the dot-source syntax so it seems that it would be possible.