繁体   English   中英

运行脚本块的 Powershell - 范围,点源

[英]Powershell running a scriptblock - scope, dot-sourcing

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

Measure-Command 是我想要的行为的一个例子。 脚本块在与 Measure-Command 本身相同的范围内运行。 如果脚本块引用了此范围内的变量,则脚本可以更改它。

附件是一个示例脚本块,它增加了 $a 变量。 当被 Measure-Command 调用时,变量会增加。 但是当被 Wrapper 函数调用时,变量不会增加——除非我对 Wrapper 函数的调用和 Wrapper 函数本身都使用点源。

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-Command 不使用点源语法,所以它似乎是可能的。

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

将函数放在module 中,以及脚本块参数的点源调用,解决了这个问题:

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

$a = 1
Wrapper { $a++ }

$a

以上产生2 ,证明脚本块在调用者的范围内执行。

有关为什么这样做以及为什么有必要的解释,请参阅相关问题的答案

注意:上面的方法没有扩展到管道使用,在那里你需要传递脚本块,这些脚本块期望使用自动变量$_来引用手头的对象(例如,
1, 2, 3 | Wrapper { $_ ... } 1, 2, 3 | Wrapper { $_ ... } ; 为了支持此用例,需要一种解决方法 - 请参阅此答案

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM