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.
The answer of user4003407 did solve my problem, but I don't find the examples very intuitive. So I'm writing this solution mainly to add an additional example.
I had the following function defined in my MyHelpers.psm1
file which was causing issues:
function ConvertTo-HashTable {
param (
[Parameter(Mandatory, ValueFromPipeline)]
$InputObject,
[scriptblock] $Key = { $InputObject },
[scriptblock] $Value = { $InputObject }
)
begin { $HashTable = @{} }
process { $HashTable.Add((& $Key), (& $Value)) }
end { $HashTable }
}
On usage:
Import-Module 'ExchangeOnlineManagement'
Import-Module 'MyHelpers'
$UserLookup = Get-User | ConvertTo-HashTable -Key { $_.Sid }
I got the error:
EXCEPTION: Exception calling "Add" with "2" argument(s): "Key cannot be null. (Parameter 'key')"
Because $_
was not bound correctly, thus returning $null
from the scriptblock.
To fix this I used ForEach-Object
to correctly bind $_
, as suggested by the answer of user4003407. So I changed the definition to:
function ConvertTo-HashTable {
param (
[Parameter(Mandatory, ValueFromPipeline)]
$InputObject,
[scriptblock] $Key = { $InputObject },
[scriptblock] $Value = { $InputObject }
)
begin { $HashTable = @{} }
process {
$HashTable.Add(
($InputObject | ForEach-Object $Key),
($InputObject | ForEach-Object $Value)
)
}
end { $HashTable }
}
I went for $InputObject | ForEach-Object $Key
instead of ForEach-Object $Key -InputObject $InputObject
, because I prefer the way it reads, but both should do the job.
If you're looking for a shorter solution you could also use its alias %
, ($InputObject | % $Key
), but the linter I'm using doesn't recommend it (AvoidUsingCmdletAliases) so I went with the full cmdlet name.