PowerShell函数与参数化脚本块

Ste*_*e B 7 powershell

我想创建一个枚举一些数据的PowerShell函数,并在所有实例中触发一个脚本块.

到现在为止(这不是实际的代码,但它说明了我的问题):

function Invoke-TenTimes
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory=$true, Position=0)]
        [ScriptBlock]$Action
    )
    process
    {
        $digits = 0..10
        $digits | % {
            $Action.Invoke($_);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我把这个功能放在我的模块中.但是,当我打电话时,我没有得到任何结果:

Invoke-TenTimes { $_ }
Run Code Online (Sandbox Code Playgroud)

输出为空白(不显示任何内容).

如果我打电话

Invoke-TenTimes { $_ -eq $null }
Run Code Online (Sandbox Code Playgroud)

我得到10个true.事实上,我看到它$_是空的.

什么是填充的正确方法$_

让我疯狂的是,如果我将此函数和调用放在同一个ps1文件中,它可以工作(但我想按需传递脚本块):

function Invoke-TenTimes
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory=$true, Position=0)]
        [ScriptBlock]$Action
    )
    process
    {
        $digits = 0..10
        $digits | % {
            $Action.Invoke($_);
        }
    }
}


Invoke-TenTimes { $_ }
Run Code Online (Sandbox Code Playgroud)

小智 5

开始了:

$scriptblock = {param($number) Write-Host "Current Number is $number"} 

function Invoke-TenTimes
{
    [CmdletBinding()]
    param
    (
       [Parameter(Mandatory=$true, Position=0)]
       [ScriptBlock]$Action
    )
    $digits = 1..10
    $digits | ForEach-Object{Invoke-Command -ScriptBlock $Action -Args $_}
 }
Run Code Online (Sandbox Code Playgroud)

使用:

Invoke-TenTimes $scriptblock
Run Code Online (Sandbox Code Playgroud)


klu*_*msy 2

这是一个范围问题,传入的脚本块属于与其执行范围不同的范围。如果传入的脚本块不必引用其上下文中的变量,您可以简单地克隆脚本块以强制它位于您正在运行它的范围内。和

$action = [scriptblock]::Create($action)
Run Code Online (Sandbox Code Playgroud)

有趣的是,它一开始只是因为意外才起作用。它从脚本块所属的父范围获取 $_ ,该脚本块恰好位于 foreach-object 内部,这很好。

但是使用你的原始版本,然后运行这个

"gotcha" | % {
Invoke-TenTimes {  $_ }
}
Run Code Online (Sandbox Code Playgroud)

你会发现你会遇到 10 次陷阱,因为 $_ 在你的调用者范围内不为 null,但它是一些东西。