I have the following method declared in a module I've called Common.psm1
:
function Test-Any ([ScriptBlock]$FilterScript = $null)
{
begin {
$done = $false
}
process {
if (!$done)
{
if (!$FilterScript -or ($FilterScript | Invoke-Expression)){
$done = $true
}
}
}
end {
$done
}
}
Set-Alias any Test-Any -Scope Global
Now in another module, I have the following validation:
$id = 1
if($notifications | any { $_.Id -eq $id })
{
# do stuff here
return
}
I receive the following error:
Invoke-Expression : The variable '$id' cannot be retrieved because it has not been set.
The interesting thing is that if I move the Test-Any
definition to the calling module, it works like a charm.
How can I make this work without copying Test-Any
to my other modules and without changing this syntax:
if($notifications | any { $_.Id -eq $id })
EDIT 1: There seems to be some debate about whether or not my code should work. Feel free to try this on your own machine:
function Test-Any ([ScriptBlock]$FilterScript = $null)
{
begin {
$done = $false
}
process {
if (!$done)
{
if (!$FilterScript -or ($FilterScript | Invoke-Expression)){
$done = $true
}
}
}
end {
$done
}
}
Set-Alias any Test-Any -Scope Global
$id = 3
$myArray = @(
@{Id = 1},
@{Id = 2},
@{Id = 3},
@{Id = 4},
@{Id = 5},
@{Id = 6},
@{Id = 7},
@{Id = 8}
)
$myEmptyArray = @()
$myArray | any #returns true
$myArray | any {$_.Id -eq $id} #returns true
$myEmptyArray | any #returns false
$myEmptyArray | any {$_.Id -eq $id} #returns false
EDIT 2:
I just discovered that you only encounter this issue, when Test-Any
resides in one loaded module and the calling code resides in a second module using Set-StrictMode -Version Latest
. If you turn off StrictMode, you don't get the error, but it also doesn't work.
EDIT 3: Needless to say this works perfectly fine:
$sb = [Scriptblock]::Create("{ `$_.Id -eq $id }")
if($notifications | any $sb)
But seriously takes away from the simplicity and intuitiveness I am trying to obtain