[英]Powershell not showing some properties of PSCustomObjects (or other Objects)
最初,在调查关于从 hash 表的数组中选择项目的问题 27373126 的答案时提示了此问题。 (与使用 Foreach-Object 或 Select-Object 和 hash 表 arguments 相比,这是获取属性的更短的方法。)
发现我可以使用脚本块 arguments 到Select-Object
获取项目,如下所示:
$hash = @{title="title1";detail="detail1"},@{title="title2";detail="detail2"}
$hash | select-object {$_.title},{$_.detail}
并且我可以通过定义如下函数来整理 output 对象(使用名为“$_.title”和“$_.detail”的属性生成):
function title{$_.title};function detail{$_.detail}
$hash | select {title},{detail}
然后,我尝试使用由属性名称列表定义的属性自动生成 output(我知道这些是错误的,这就是我发现我所质疑的问题的方式):
'title','detail' | foreach { $hash | select $_ }
title
-----
# 4 blank lines
我知道为什么有 4 个空行。 $hash
中没有 "title" 成员,它是一个 "title" item 。 令人惊讶的部分是没有“详细信息”栏。 试过这个:
'title','detail' | foreach { $hash | select $_ } | gm
TypeName: Selected.System.Collections.Hashtable
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
title NoteProperty object title=null
Foreach-Object 向Select-Object
Object 提供 arguments 可能有些奇怪。 试过:
$hash | select title; $hash|select detail
title
-----
# 4 blank lines
哪个命令正在生成 output?:
'start';$hash|select title;'in';$hash|select detail;'done'
start
title
-----
in
done
所以每个部分有 2 个空行,但没有“详细”成员。 是时候更具体一点了:
'start';$hash|select title|gm;'in';$hash|select detail|gm;'done'
start
TypeName: Selected.System.Management.Automation.Internal.Host.InternalHost
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
title NoteProperty object title=null
in
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
detail NoteProperty object detail=null
done
所以第二个select正在生成一个“详细”成员,但它在某处迷路了。 这个怎么样:
&{$hash|select title;$hash|select detail}|gm
TypeName: Selected.System.Management.Automation.Internal.Host.InternalHost
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
title NoteProperty object title=null
没有“细节”了。 经过大量徒劳的测试,一些有用的研究发现了部分答案。 完整的描述在PowerShell 格式化和输出如何真正起作用,但结果是最终显示由第一个 object 通过管道的属性控制。 这个 object 有一个“title”属性,但没有“detail”属性,所以 output 被格式化为匹配。 这就解释了为什么显示的 output 没有“详细信息”列但为什么最后一个Get-Member
没有显示它? Get-Member
应该收到 2 个带有“标题”的对象,然后是 2 个带有“详细信息”的对象。 我知道这一点是因为手动Get-Member
确实显示了它们:
&{$hash|select title;$hash|select detail}|foreach{[componentmodel.typedescriptor]::getproperties($_)[0].name}
title
title
detail
detail
# Can't use gettype() since doesn't know about added properties
因此,似乎不仅仅是Format-Table
根据管道中的第一个 object 决定其 output。 显然, Get-Member
也表现出这种行为,尽管在这种情况下它是每种类型的第一个 object 。 所有对象都是PSCustomObjects
,但第一个对象只有一个“标题”添加属性,因此Get-Member
假定所有PSCustomObjects
看起来都一样。
最后,问题。 哪些其他 cmdlet(如果有)表现出这种“管道中的第一个 object 默默地定义后续行为”功能?
注意:在7.0 之前的 PowerShell 版本中,确实不支持 hash 表作为Select-Object
的输入; 在早期版本中,首先将它们转换为[pscustomobject]
; 例如: [pscustomobject] @{title="title1";detail="detail1"}, [pscustomobject] @{title="title2";detail="detail2"} | Select-Object title, detail
回顾一下您已经知道的问题:(可能是隐式的) Format-Table
output 将第一个object 的属性锁定为显示列,不具有这些属性的后续对象将显示空白列值- 请参阅此答案细节。
需要注意的是,这仅仅是一个显示问题。
Get-Member
问题略有不同:它不是关于第一个输入对象的类型,而是关于共享相同类型的输入对象: Get-Member
旨在为输入对象中的每个不同类型生成 output。
问题是两个[pscustomobject]
实例(例如Select-Object
的 output )被Get-Member
认为是同一类型(从 .NET 的角度来看,它们在技术上是)-即使它们具有不同的属性,所以Get-Member
实际上只显示输入对象中第一个[pscustomobject]
实例的成员(可能是也可能不是第一个输入 object整体)。
因此,为了 pipe 多个[pscustomobject]
实例到Get-Member
并查看每个的属性,请通过ForEach-Object
调用Get-Member
:
# Two sample [pscustomobject] instances with non-overlapping properties.
$objs = [pscustomobject] @{ foo = 1 }, [pscustomobject] @{ bar = 2 }
# Call Get-Member on *each* object.
$objs | ForEach-Object { Get-Member -InputObject $_ }
至于:
问题。 哪些其他 cmdlet(如果有)表现出这种“管道中的第一个 object 默默地定义后续行为”功能?
除了(可能隐式应用) Format-Table
之外,本质上,所有期望所有输入对象为同一类型(具有相同属性集)的 cmdlet 都表现出这种行为,尤其是Export-Csv
/ ConvertTo-Csv
。 任何数量的第三方 cmdlet 也可能属于该类别 - 无法提供详尽的列表,尤其是因为将来可能会引入新的 cmdlet。
您通常可以从 cmdlet 的目的推断它是否需要统一输入(希望文档也清楚说明):
Export-Csv
和ConvertTo-Csv
,因为它们创建表格数据,需要统一输入; 虽然您可以使用-Force
和-Append
来制作与预先存在的 CSV 文件具有不同属性的Export-Csv
append 对象,但仅添加与预先存在的列(属性)匹配的新添加对象上存在的那些属性,因此一致性是最终还是被强制执行。
相比之下, ConvertTo-Json
,因为它可以序列化任意object 图,所以不需要统一输入。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.