问题
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