未显示所有属性

Not all properties displayed

当我们尝试通过管道将数据导出到其他函数时,我们在 PowerShell 中观察到一些奇怪的行为。

示例代码:

$Array = @()

$Obj1 = [PSCustomObject]@{
    Member1   = 'First'
    Member2   = 'Second'
}

$Obj2 = [PSCustomObject]@{
    Member1   = 'First'
    Member2   = 'Second'
    Member3   = 'Third'
}

$Array = $Obj1, $Obj2
$Array | Out-GridView -Title 'Not showing Member3'

$Array = $Obj2, $Obj1
$Array | Out-GridView -Title 'All members correctly displayed'

在上面的示例中,您可以看到当第一个对象仅包含 2 properties 时,Out-GridView CmdLet(和其他)仅显示 2 properties,即使第二个对象有 3 properties。但是,当数组中的第一个对象有 3 个 properties 时,它会正确显示它们。

有办法解决这个问题吗?因为无法预先预测一个对象上会有多少 properties,以及具有最多 properties 的对象是否会成为 array 中的第一个。

我曾经有过同样的经历并创建了以下可重用的“Union”函数:

# 2021-08-25 Removed Union function

用法:

$Obj1, $Obj2 | <b>Union</b> | Out-GridView -Title 'Showing all members'

它还可以处理复杂的对象。一些标准 cmdlet 一次输出多个对象类型,如果您查看它们(例如 Out-GridView)或将它们转储到一个文件中(例如 Export-Csv),您可能会错过很多属性。再举个例子:

Get-WmiObject -Namespace root/hp/instrumentedBIOS -Class hp_biosSetting | <b>Union</b> | Export-Csv ".\HPBIOS.csv"

2014-09-19 添加:

也许这已经在评论的字里行间 $Array | Select * | … 不会解决问题,但专门选择属性 $Array | Select Member1, Member2, Member3 | … 可以。
此外,虽然在大多数情况下 Union 函数会起作用,但也有一些例外,因为它只会将 first 对象与其余对象对齐。 考虑以下对象:

$List = @(
    New-Object PSObject -Property @{Id = 2}
    New-Object PSObject -Property @{Id = 1}
    New-Object PSObject -Property @{Id = 3; Name = "Test"}
)

如果你 Union 这个对象,一切似乎都很好,如果你,例如ExportTo-CSV 并使用 export .csv 文件从那时起你将永远不会有任何问题。

$List | Union
Id Name
-- ----
 2
 1
 3 Test

仍然有问题,因为只有第一个对象对齐。如果你例如在 Id (Sort Id) 上对结果进行排序或只取最后 2 (Select -Last 2) 个条目,Name 未列出,因为第二个对象不包含 Name 属性:

$List | Union | Sort Id
Id
--
 1
 2
 3

因此我重写了 Union-Object(别名 Union)函数`):

联合对象

# 2021-08-25 Removed Union-Object function

语法:

$Array | Union | Out-GridView -Title 'All members correctly displayed'

更新2021-08-25

基于 az1d 对因 属性 名称大小写不同而导致的错误的有用反馈,我创建了一个新的 UnifyProperties 函数。
(我不会再用他的名字UnionObject

function UnifyProperties {
  $Names = [System.Collections.Generic.HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase)
  $InputCollected = @($Input)
  $InputCollected.ForEach({ 
    foreach ($Name in $_.psobject.Properties.Name) { $Null = $Names.Add($Name) }
  })
  $inputCollected | Select-Object @($Names)
}

用法:

[pscustomobject] @{ one = 1; two = 2; three = 3 },
[pscustomobject] @{ ONE = 10; THREE = 30; FOUR = 4 } |
    UnifyProperties

one two three FOUR
--- --- ----- ----
  1   2     3
 10        30 4

另请参阅:#13906 Add -UnifyProperties parameter to Select-Object