Function Powershell运行scriptblock-作用域,点源

Function Powershell运行scriptblock-作用域,点源,function,powershell,scope,Function,Powershell,Scope,我想编写一个函数,该函数接受scriptblock作为参数,并在调用它的范围内执行该scriptblock Measure命令是我想要的行为的一个示例。scriptblock在与Measure命令本身相同的范围内运行。如果scriptblock引用此范围内的变量,则脚本可以对其进行更改 附加的是一个示例scriptblock,它增加了$a变量。当通过Measure命令调用时,变量将递增。但是当由包装器函数调用时,变量不会递增——除非我点源代码包装器函数的调用和包装器函数本身都使用点源代码 fun

我想编写一个函数,该函数接受scriptblock作为参数,并在调用它的范围内执行该scriptblock

Measure命令是我想要的行为的一个示例。scriptblock在与Measure命令本身相同的范围内运行。如果scriptblock引用此范围内的变量,则脚本可以对其进行更改

附加的是一个示例scriptblock,它增加了$a变量。当通过Measure命令调用时,变量将递增。但是当由包装器函数调用时,变量不会递增——除非我点源代码包装器函数的调用和包装器函数本身都使用点源代码

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"
运行此代码的结果是:

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
虽然最后一个选项有效,但我希望避免调用Wrapper2的点源语法。这可能吗?Measure命令没有使用点源语法,因此它似乎是可能的。

,正如他惯常做的那样,在对问题的简短评论中提供了关键指针:

将函数放在模块中,再加上脚本块参数的点源调用,可以解决以下问题:

$null = New-Module {
  function Wrapper {
    param($ScriptBlock)
    . $ScriptBlock
  }
}

$a = 1
Wrapper { $a++ }

$a
上面给出了
2
,证明脚本块在调用方的作用域中执行

有关此操作的作用和必要性的解释,请参见相关问题


注意:上述方法没有扩展到管道使用,在管道使用中,您将希望传递希望使用自动变量
$\uz
引用手头对象的脚本块(例如,
1,2,3 |包装器{$\uz…}
;要支持此用例,需要一种变通方法-请参阅。

将包装函数放入模块中。