Function does not get binding when used in Module

左心房为你撑大大i 提交于 2019-12-01 05:43:44

问题


I'm trying to put this function:

function Test-Any {
    [CmdletBinding()]
    param($EvaluateCondition,
        [Parameter(ValueFromPipeline = $true)] $ObjectToTest)
    begin {
        $any = $false
    }
    process {
        if (-not $any -and (& $EvaluateCondition $ObjectToTest)) {
            $any = $true
        }
    }
    end {
        $any
    }
}

into a module. I just created a new module, the my-scripts.psm1 file, which contains just the above function and import it with Import-Module <absolute path>.

The problem is that if I use the function from the module 1..4 | Test-Any { $_ -gt 3 } returns false, because $_ is not set to the value from the pipe.

If I define the function normally in a script and use it from there it works as expected (with $_ getting assigned the integer values).

This happens with PowerShell v4.0 under Windows 7.


回答1:


That command: & $EvaluateCondition $ObjectToTest — does not bind anything to $_. In absence of a param() block in ScriptBlock, the value of $ObjectToTest will be bound to $args[0].

$SB = {"`$_: '$_'; `$args[0]:'$($args[0])'"}
1..3 | ForEach-Object {& $SB ($_+3)}

Output:

$_: '1'; $args[0]:'4'
$_: '2'; $args[0]:'5'
$_: '3'; $args[0]:'6'

Why does referencing $_ work: you simply reference the $_ variable from the parent scope.

The value of $_ that you see, is a current pipeline input object, passed to the Test-Any function.

function Test-Any {
    param($EvaluateCondition)
    process {
        "Test-Any `$_: '$_'"
        & $EvaluateCondition
    }
}
1..2 | %{3..4 | Test-Any {"EvaluateCondition `$_:'$_'"}}

Output:

Test-Any $_: '3'
EvaluateCondition $_:'3'
Test-Any $_: '4'
EvaluateCondition $_:'4'
Test-Any $_: '3'
EvaluateCondition $_:'3'
Test-Any $_: '4'
EvaluateCondition $_:'4'

When you define Test-Any in module scope, then variable $_ with pipeline input to Test-Any also got defined in that module scope and was not available outside of it.

New-Module {
    function Test-Any {
        param($EvaluateCondition)
        process {
            "Test-Any `$_: '$_'"
            & $EvaluateCondition
        }
    }
} | Out-Null
1..2 | %{3..4 | Test-Any {"EvaluateCondition `$_:'$_'"}}

Output:

Test-Any $_: '3'
EvaluateCondition $_:'1'
Test-Any $_: '4'
EvaluateCondition $_:'1'
Test-Any $_: '3'
EvaluateCondition $_:'2'
Test-Any $_: '4'
EvaluateCondition $_:'2'

If you want to invoke a script block with some value bound to $_, then one way to do this would be:

ForEach-Object $EvaluateCondition -InputObject $ObjectToTest


来源:https://stackoverflow.com/questions/33232360/function-does-not-get-binding-when-used-in-module

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!