【问题标题】:Not all properties displayed未显示所有属性
【发布时间】:2017-06-08 06:28:54
【问题描述】:

当我们尝试通过管道将数据导出到其他函数时,我们在 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 中的第一个。

【问题讨论】:

  • "因为不可能从一个对象上有多少属性来预测" - 嗯..是的,你控制对象是什么,你控制您放入其中的属性。它们不是随机的..在每个对象上选择你想要的,然后它就会起作用..
  • 没错,但问题是我的代码会根据某些逻辑生成额外的比例。所以有些对象只有 2 个,而其他对象可能有 15 个 ..
  • 我认为,powershell 只是认为alright, I can predict [PSCustomObjects] with same props are coming - lets stop looking at it after the first one。您应该能够以相同的方式设置所有对象。从技术上讲,您返回了一个 [ADUser 对象和一个 [DateTime] 并且对结果很奇怪感到惊讶。
  • "没错,但问题是我的代码会根据某些逻辑生成额外的比例。所以有些对象只有 2 个,而其他对象可能有 15 个。" - 你可以告诉这个这是一个糟糕的设计,因为它不能很好地工作。 :-|数据模型具有您关心的字段,如果一个实例对该字段没有值,则将该值留空。例如在 CSV 中,您可以将某列连续留空,但不能从一行中取出一列,否则整个 CSV 会中断。
  • This 是生成属性的函数。你可以看到它从一开始就不知道会有多少属性。如果这是糟糕的设计,我必须重新考虑最后如何添加空属性。类似$Array | ForEach-Object {$_.PSObject.Properties.Name} | Sort-Object -Unique

标签: arrays powershell properties unify


【解决方案1】:

我曾经有过同样的经历,并创建了以下可重用的“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 年 9 月 19 日添加:

也许这已经在 cmets 中的行之间 $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) 上对结果进行排序或只取最后两个 (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 年 8 月 25 日更新

基于az1d对属性名称不同、大小写相同导致的错误的有用反馈,我创建了一个新的UnifyProperties函数。
(我将不再使用名称@ 987654349@ 为他)

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

【讨论】:

  • 热爱并依赖Union-Object,感谢您创造它。一个副作用是不断出现数百个错误选择:无法处理该属性,因为该属性“示例”已经存在。 $对象 | Select ([String[]]($Property | Select -Unique)) 代码似乎仍然运行良好,我得到了我期望的结果(没有丢失的列),但除了放置“$Objects | Select ([String[] ]($Property | Select -Unique) | out-null" 我不知道这个错误显示背后是否有原因
  • 我终于找到了这段代码的bug所在。它与Select -Unique 一起使用,它区分大小写,因此如果您有多个属性相同但大小写不同(例如firefox 和FIREFOX),那么Select -Unique 并不总是只返回其中一个github.com/PowerShell/PowerShell/issues/12059,然后$Objects | Select $Property 失败因为两个不同的大小写,但相同的命名属性仍然存在。解决方法是使用Sort -Unique 而不是Select -Unique
  • 更好的是,我创建了一个保留原始排序顺序的独特方法:($Property | Group-Object -NoElement).Name | Get-Unique,因此最后一行将变为$Objects | Select ([String[]]($Property | Group-Object -NoElement).Name | Get-Unique)
  • 感谢您的反馈,我已经相应地更新了答案。
猜你喜欢
  • 1970-01-01
  • 2018-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多