简体   繁体   English

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

[英]Powershell not showing some properties of PSCustomObjects (or other Objects)

Originally, this question was prompted while investigating an answer to question 27373126 about selecting items from an array of hash tables.最初,在调查关于从 hash 表的数组中选择项目的问题 27373126 的答案时提示了此问题。 (This was about shorter ways to get the properties than using Foreach-Object or Select-Object with hash table arguments.) (与使用 Foreach-Object 或 Select-Object 和 hash 表 arguments 相比,这是获取属性的更短的方法。)

Having found that I could get items using script-block arguments to Select-Object as follows:发现我可以使用脚本块 arguments 到Select-Object获取项目,如下所示:

$hash = @{title="title1";detail="detail1"},@{title="title2";detail="detail2"}
$hash | select-object {$_.title},{$_.detail}

and that I could tidy up the output objects (produced with properties named "$_.title" and "$_.detail") by defining functions as follows:并且我可以通过定义如下函数来整理 output 对象(使用名为“$_.title”和“$_.detail”的属性生成):

function title{$_.title};function detail{$_.detail}
$hash | select {title},{detail}

I then tried to automate producing output with properties defined by a list of property names (I know these are wrong, this is just how I found the issue I am questioning):然后,我尝试使用由属性名称列表定义的属性自动生成 output(我知道这些是错误的,这就是我发现我所质疑的问题的方式):

'title','detail' | foreach { $hash | select $_ }

title
-----





# 4 blank lines

I know why there are 4 blank lines.我知道为什么有 4 个空行。 There is no "title" member in $hash , it is a "title" item . $hash中没有 "title" 成员,它是一个 "title" item The surprising part was no column for "detail".令人惊讶的部分是没有“详细信息”栏。 Tried this:试过这个:

'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

Maybe something strange with Foreach-Object providing arguments to Select-Object . Foreach-Object 向Select-Object Object 提供 arguments 可能有些奇怪。 Tried:试过:

$hash | select title; $hash|select detail

title
-----





# 4 blank lines

Which command is generating the output?:哪个命令正在生成 output?:

'start';$hash|select title;'in';$hash|select detail;'done'
start

title
-----


in


done

So 2 blank lines from each section but no "detail" member.所以每个部分有 2 个空行,但没有“详细”成员。 Time to get a bit more specific:是时候更具体一点了:

'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

So the second select IS generating a "detail" member but it is getting lost somewhere.所以第二个select正在生成一个“详细”成员,但它在某处迷路了。 How about this:这个怎么样:

&{$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

No "detail" again.没有“细节”了。 After lots of fruitless testing, some useful research uncovered a partial answer.经过大量徒劳的测试,一些有用的研究发现了部分答案。 The full description is in How PowerShell Formatting and Outputting REALLY works but the upshot is that the final display was being controlled by the properties of the first object through the pipeline.完整的描述在PowerShell 格式化和输出如何真正起作用,但结果是最终显示由第一个 object 通过管道的属性控制。 This object had a "title" property but no "detail" property so the output was formatted to match.这个 object 有一个“title”属性,但没有“detail”属性,所以 output 被格式化为匹配。 That explains why the displayed output had no "detail" column but why did the last Get-Member not show it?这就解释了为什么显示的 output 没有“详细信息”列但为什么最后一个Get-Member没有显示它? Get-Member should have received 2 objects with a "title" followed by 2 objects with a "detail". Get-Member应该收到 2 个带有“标题”的对象,然后是 2 个带有“详细信息”的对象。 I know this because a manual Get-Member does show them:我知道这一点是因为手动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

So it would seem that not just Format-Table decides its output based on the first object down the pipeline.因此,似乎不仅仅是Format-Table根据管道中的第一个 object 决定其 output。 Apparently, Get-Member also exhibits this behaviour, though in this case it is the first object of each type .显然, Get-Member也表现出这种行为,尽管在这种情况下它是每种类型的第一个 object 。 All the objects were PSCustomObjects but the first had only a "title" added property so Get-Member assumed that all PSCustomObjects looked the same.所有对象都是PSCustomObjects ,但第一个对象只有一个“标题”添加属性,因此Get-Member假定所有PSCustomObjects看起来都一样。

And finally, THE QUESTION .最后,问题 Which other cmdlets, if any, exhibit this "first object down the pipeline silently defines subsequent behaviour" functionality?哪些其他 cmdlet(如果有)表现出这种“管道中的第一个 object 默默地定义后续行为”功能?

Note: In PowerShell versions before 7.0 , hash tables indeed aren't supported as input to Select-Object ;注意:在7.0 之前的 PowerShell 版本中,确实不支持 hash 表作为Select-Object的输入; in earlier versions, cast them to [pscustomobject] first;在早期版本中,首先将它们转换为[pscustomobject] eg:例如:
[pscustomobject] @{title="title1";detail="detail1"}, [pscustomobject] @{title="title2";detail="detail2"} | Select-Object title, detail

To recap the problem that you're already aware of: (possibly implicit) Format-Table output locks in the properties of the first object as display columns and subsequent objects that do not have these properties will show blank column values - see this answer for details.回顾一下您已经知道的问题:(可能是隐式的) Format-Table output 将第一个object 的属性锁定为显示列,不具有这些属性的后续对象将显示空白列值- 请参阅此答案细节。
It is important to note that this is merely a display problem.需要注意的是,这仅仅是一个显示问题。

The Get-Member problem is slightly different: it isn't about the first input object's type, it's about input objects that share the same type : Get-Member is designed to produce output for each distinct type among the input objects. Get-Member问题略有不同:它不是关于第一个输入对象的类型,而是关于共享相同类型的输入对象: Get-Member旨在为输入对象中的每个不同类型生成 output。

The problem is that two [pscustomobject] instances (such as output by Select-Object ) are considered the same type by Get-Member (which, from a .NET perspective, they technically are ) - even if they have different properties , so Get-Member will in effect only show the members of the first [pscustomobject] instance among the input objects (which may or may not be the first input object overall ).问题是两个[pscustomobject]实例(例如Select-Object的 output )Get-Member认为是同一类型(从 .NET 的角度来看,它们在技术上)-即使它们具有不同的属性,所以Get-Member实际上只显示输入对象中第一个[pscustomobject]实例的成员(可能是也可能不是第一个输入 object整体)。

Therefore, in order to pipe multiple [pscustomobject] instances to Get-Member and see the properties of each , call Get-Member via ForEach-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 $_ }

As for:至于:

THE QUESTION.问题。 Which other cmdlets, if any, exhibit this "first object down the pipeline silently defines subsequent behaviour" functionality?哪些其他 cmdlet(如果有)表现出这种“管道中的第一个 object 默默地定义后续行为”功能?

In addition to (potentially implicitly applied) Format-Table , in essence all cmdlets that expect all input objects to be of the same type (have the same set of properties) exhibit the behavior , notably Export-Csv / ConvertTo-Csv .除了(可能隐式应用) Format-Table之外,本质上,所有期望所有输入对象为同一类型(具有相同属性集)的 cmdlet 都表现出这种行为,尤其是Export-Csv / ConvertTo-Csv Any number of third-party cmdlets may fall into that category as well - there's no way to come up with an exhaustive list, not least because new cmdlets may be introduced in the future.任何数量的第三方 cmdlet 也可能属于该类别 - 无法提供详尽的列表,尤其是因为将来可能会引入新的 cmdlet。

You can generally infer from the purpose of a cmdlet whether it requires uniform input or not (and, hopefully, the documentation makes it clear too):您通常可以从 cmdlet 的目的推断它是否需要统一输入(希望文档也清楚说明):

  • Export-Csv and ConvertTo-Csv , because they create tabular data, require uniform input; Export-CsvConvertTo-Csv ,因为它们创建表格数据,需要统一输入; while you can use -Force with -Append to make Export-Csv append objects that also have different properties to a preexisting CSV file, only those properties present on the newly added objects that match the preexisting columns (properties) are added, so uniformity is ultimately still enforced.虽然您可以使用-Force-Append来制作与预先存在的 CSV 文件具有不同属性的Export-Csv append 对象,但仅添加与预先存在的列(属性)匹配的新添加对象上存在的那些属性,因此一致性是最终还是被强制执行。

  • By contrast, ConvertTo-Json , because it can serialize arbitrary object graphs , does not require uniform input.相比之下, ConvertTo-Json ,因为它可以序列化任意object 图,所以不需要统一输入。

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

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