繁体   English   中英

Powershell 未显示 PSCustomObjects(或其他对象)的某些属性

[英]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-CsvConvertTo-Csv ,因为它们创建表格数据,需要统一输入; 虽然您可以使用-Force-Append来制作与预先存在的 CSV 文件具有不同属性的Export-Csv append 对象,但仅添加与预先存在的列(属性)匹配的新添加对象上存在的那些属性,因此一致性是最终还是被强制执行。

  • 相比之下, ConvertTo-Json ,因为它可以序列化任意object 图,所以不需要统一输入。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM