Measure-Command 如何在父作用域中调用 ScriptBlock?

Zer*_*tul 6 powershell scope

在下面的示例中,Measure-Command变量x更新后,但在示例中我自己的命令版本x保持不变。

$x = 0
Measure-Command -Expression { $x++ } | Out-Null
$x # outputs 1

function Measure-Command2
{
    param([ScriptBlock]$Expression)
    . $Expression
}
$x = 0
Measure-Command2 -Expression { $x++ }
$x # outputs 0
Run Code Online (Sandbox Code Playgroud)

我可以在自己的函数中使用同样的魔法吗?

mkl*_*nt0 4

最用户友好的解决方案是在动态模块中定义您的函数,使用
New-Module

$null = New-Module {
  function Measure-Command2 {
    param([ScriptBlock]$Expression)
    . $Expression
  }
}

$x = 0
Measure-Command2 -Expression { $x++ }
$x # outputs *1* now, as desired.
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 模块在其自己的范围域(也称为会话状态)中运行,与调用者的域不同。因此,与非模块函数不同,在调用时不会创建调用者作用域的子作用域。

  • 作为参数传递的脚本块,由于是{ ... }在调用者的作用域中创建为文字 ( ) 的,因此调用者的作用域中执行,而不是在函数的作用域中执行。


如果没有模块,您需要对自身的调用进行点源调用,因为函数和脚本默认在子作用域中运行:Measure-Command2

function Measure-Command2 {
  param([ScriptBlock]$Expression)
  . $Expression
}
$x = 0
# Note the dot-sourcing
. Measure-Command2 -Expression { $x++ }
$x # outputs *1* now, as desired.
Run Code Online (Sandbox Code Playgroud)