不是所有属性都显示。

9
当我们试图通过管道导出数据到其他功能中时,我们观察到在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个属性时,Out-GridView CmdLet(和其他CmdLet)仅显示2个属性,即使第二个对象有3个属性。但是,当数组中的第一个对象具有3个属性时,它确实正确地显示了所有这些属性。
有没有办法解决这个问题?因为不可能预测对象上会有多少属性,以及具有最多属性的对象是否将成为array中的第一个对象。

“因为无法预测对象上会有多少属性,”这是错误的。你可以控制对象的属性,你可以选择在每个对象上添加你需要的属性,这样就能够实现预测了。” - TessellatingHeckler
真的,但问题是我的代码根据某些逻辑生成额外的属性。因此,有些对象只有2个属性,而其他对象可能有15个属性。 - DarkLite1
我认为,PowerShell只是认为“好的,我可以预测[PSCustomObjects]将具有相同的属性 - 让我们在第一个之后停止查看它”。您应该能够通过以相同的方式设置所有对象来进行操作。从技术上讲,您正在返回一个[ADUser]对象和一个[DateTime],并且对结果感到惊讶。 - restless1987
这是生成属性的函数。你可以看到它不知道从一开始就会有多少属性。如果这是不好的设计,我必须重新考虑如何在最后添加空属性。类似于 $Array | ForEach-Object {$_.PSObject.Properties.Name} | Sort-Object -Unique 的东西。 - DarkLite1
我认为这是你需要执行的操作:创建一个包含所有可能属性的数组,并在Select-Object中使用它。在你的示例中,它是有效的。 - restless1987
显示剩余3条评论
1个回答

10

我曾经有过同样的经历,并创建了以下可重复使用的 'Union' 函数:

# 2021-08-25 Removed Union function

使用方法:

$Obj1, $Obj2 | Union | 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年9月19日:

也许这已经在评论中暗示了,$Array | Select * | ...并不能解决问题,但是明确选择属性$Array | Select Member1, Member2, Member3 | ...可以。
此外,尽管在大多数情况下Union函数将起作用,但也有一些例外情况,因为它只会将第一个对象与其他对象对齐。 考虑以下对象:

$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)对结果进行排序,或者仅选取最后两个 (Select -Last 2) 条目,则不会列出Name,因为第二个对象不包含Name属性:

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

因此,我已经重新编写了`Union-Object`(别名为`Union`)函数:

Union-Object

# 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 为 Select-Object 添加 -UnifyProperties 参数


热爱并依赖Union-Object,感谢您的创造。唯一的副作用是不断出现数百个错误。选择:无法处理属性,因为属性“example”已经存在。$Objects | Select ([String[]]($Property | Select -Unique))。 虽然代码似乎仍然可以正常工作并得到预期结果(没有丢失列),但除了将“$Objects | Select ([String[]]($Property | Select -Unique) | out-null”放入其中之外,我不知道这个错误显示背后是否有什么原因。 - az1d
1
我终于找到了这段代码中的错误所在。问题出在 Select -Unique 上,它是区分大小写的。如果你有多个属性名称相同但大小写不同(例如 firefox 和 FIREFOX),那么 Select -Unique 并不总是只返回其中一个。https://github.com/PowerShell/PowerShell/issues/12059 然后 $Objects | Select $Property 会因为两个不同大小写但同名的属性仍然存在而失败。解决方法是使用 Sort -Unique 而不是 Select -Unique - az1d
1
更好的是,我创建了一个独特的方法,保留了原始的排序顺序:($Property | Group-Object -NoElement).Name | Get-Unique,因此完整的最后一行将变为 $Objects | Select ([String[]]($Property | Group-Object -NoElement).Name | Get-Unique) - az1d
1
感谢您的反馈,我已经相应地更新了答案。 - iRon
1
在我的服务器上,$Names=System.Collections.Generic.HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase) 因为我的 Powershell 版本比较旧(不支持 'new')而失败了。但是这个可行:$Names = New-Object -TypeName 'System.Collections.Generic.HashSet[String]' -ArgumentList ([StringComparer]::InvariantCultureIgnoreCase) - casewolf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接