我想创建一个枚举一些数据的PowerShell函数,并在所有情况下触发脚本块。

到目前为止,我已经有了(这不是实际的代码,但是它说明了我的问题):

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

我将此功能放在模块中。但是,致电时我没有得到任何结果:
Invoke-TenTimes { $_ }

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

如果我打电话
Invoke-TenTimes { $_ -eq $null }

我得到十个true。实际上,我看到$_为null。

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

使我发疯的是,如果我将此函数和调用放在同一个ps1文件中,则可以正常工作(但我想按需传递脚本块):
function Invoke-TenTimes
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory=$true, Position=0)]
        [ScriptBlock]$Action
    )
    process
    {
        $digits = 0..10
        $digits | % {
            $Action.Invoke($_);
        }
    }
}


Invoke-TenTimes { $_ }

最佳答案

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

$action = [scriptblock]::Create($action)

有趣的是,它仅在事故发生时才起作用。它是从脚本块所属的父范围中获取了$ _,恰好在您的foreach-object内部,这很好。

但是使用您的原始版本,然后运行
"gotcha" | % {
Invoke-TenTimes {  $_ }
}

并且您会看到获得10次提示,因为$ _在您的调用方作用域中不是null,而是某种东西。

08-25 23:35