Using PowerShell Core 6.1 on Mac. It appears that piping an array to ForEach-Object is modifying or wrapping each element such that the -is operator considers all of them to be PSCustomObjects.
Let me demonstrate:
Set up an array of four items of different types (use of JSON because that's where the data is coming from in my real use case):
$a = '[4, "Hi", {}, true]' | ConvertFrom-Json
Iterate the list by index and determine which ones are PSCustomObjects:
0..3 | ForEach-Object {
$v = $a[$_]
$t = $v.GetType().FullName
$is = $v -is [PSCustomObject]
"$t - $is"
}
The output (for me) is exactly what I would expect:
System.Int64 - False
System.String - False
System.Management.Automation.PSCustomObject - True
System.Boolean - False
But if I just pipe the array to ForEach-Object:
$a | ForEach-Object {
$v = $_
$t = $v.GetType().FullName
$is = $v -is [PSCustomObject]
"$t - $is"
}
Now the output claims that all four are PSCustomObjects:
System.Int64 - True
System.String - True
System.Management.Automation.PSCustomObject - True
System.Boolean - True
Could anyone explain what is happening here?
PetSerAl, as he frequently does, has provided the crucial pointer in a comment:
Piping objects to
ForEach-Object
wraps them in a[psobject]
instance (as reflected in$_
/$PSItem
), which causes-is [pscustomobject]
/-is [psobject]
to return$True
for any input object, because - confusingly -[pscustomobject]
is the same as[psobject]
: they're both type accelerators for[System.Management.Automation.PSObject]
- against what one would expect,[pscustomobject]
is not short for[System.Management.Automation.PSCustomObject]
.Therefore, test the input objects for being instances of
[System.Management.Automation.PSCustomObject]
rather than[pscustomobject]
:Note that if you use a
foreach
loop, even-is [pscustomobject]
would work, because the objects being enumerated are then not wrapped in an extra[psobject]
instance:This works, because even a bona fide
[System.Management.Automation.PSCustomObject]
is technically also a[System.Management.Automation.PSObject]
behind the scenes.