背景:
我有一个PSCustomObject,它是通过... | convertfrom-json
转换JSON数组而创建的。该对象有许多其他属性值对象(基本上它是许多PSCustomObject的集合)。根据对对象的了解,我知道它至少包含三种不同类型的对象(类型意味着具有不同属性的PSCustomObject)。
问题:
当运行Get-Members I时,只有两个对象类型及其成员,第三个对象类型根本没有列出。我知道还有第三种对象类型,因为我可以选择仅在该对象中可用的属性。
注意:
我曾经遇到过一个类似的问题,一些成员只有在$object | select...
方法中首先被调用时才会出现在get-member
的结果中,否则他们就不会出现。我当时也没弄明白。当前的问题不是相同的,但可能是相关的,因为我尝试了$object | select...
的方法,但没有帮助。
注2:
我确实注意到,当尝试发布可重复的代码时,我只得到一个对象类型的回报,而不是从invoke-restmethod
获得的两个对象类型,这让我的问题变得更加严重,这里发生了什么,为什么一些对象类型被返回,而另一些对象类型没有返回。
示例:
Get-Members结果示例
$res.address_objects.ipv4 | gm
TypeName: Selected.System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
host NoteProperty System.Management.Automation.PSCustomObject <snip>
name NoteProperty string name=<snip>
uuid NoteProperty string uuid=<snip>
zone NoteProperty string zone=<snip>
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
name NoteProperty string name=<snip>
network NoteProperty System.Management.Automation.PSCustomObject <snip>
uuid NoteProperty string uuid=<snip>
如您所见,这里有两种对象类型,它们都有一些不同的属性名称。
示例:
示例Json,我将其转换为对象。
摘自@Jawad的回答。
请注意:此示例不是我的代码的完全副本,因为我的psobject是invoke-restmethod
自动将json转换为对象的结果。
$json = @"
{
"address_objects": {
"ipv4": [{
"host": "hostValue",
"name": "hostName",
"uuid": "value",
"zone": "thisZone"
},
{
"name": "NewName",
"network": "newNetwork",
"uuid": "thisUuid"
},
{
"name": "NewName",
"range": "newrange",
"uuid": "thisUuid"
}]
}
}
"@ | ConvertFrom-Json
运行Get-member
时预期输出:
$json.address_objects.ipv4 | gm
TypeName: Selected.System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
host NoteProperty System.Management.Automation.PSCustomObject <snip>
name NoteProperty string name=<snip>
uuid NoteProperty string uuid=<snip>
zone NoteProperty string zone=<snip>
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
name NoteProperty string name=<snip>
network NoteProperty System.Management.Automation.PSCustomObject <snip>
uuid NoteProperty string uuid=<snip>
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
name NoteProperty string name=<snip>
range NoteProperty System.Management.Automation.PSCustomObject <snip>
uuid NoteProperty string uuid=<snip>
基本上,有三个截然不同的psCustomObject,因此get-member
应该会将它们全部列出。
编辑#1:
感谢评论者的编辑,他们是正确的,所以我添加了一个可重现的样本,并澄清了我所询问的问题。我还没有深入剖析给出的答案。
1条答案
按热度按时间efzxgjgh1#
Get-Member
在设计上列出了其输入对象中的不同类型。然而,**
[pscustomobject]
示例的问题是Get-Member
无法将它们识别为不同的类型即使它们具有不同的属性。下面的代码意外地只生成一个Single输出对象,仅显示First
[pscustomobject]
示例的成员:Get-Member
仅通过类型的(完整)类型名称区分类型,如隐藏示例属性.pstypenames
的第一个元素(.pstypenames[0]
**)所示,不考虑给定示例的特定属性。默认情况下,
[pscustomobject]
示例的类型名称为System.Management.Automation.PSCustomObject
。请注意,默认情况下,
.pstypenames[0]
包含与.GetType().FullName
相同的类型名称,但是可以插入“虚构的”名称[2],这就是由Select-Object
cmdlet创建的[pscustomobject]
示例所发生的情况(请参见底部部分)。解决方法:
注意:以下代码适用于Display输出(考虑到
Get-Member
输出通常用于视觉检查,因此应该可以)。Group-Object
用于使用已计算的属性(通过为每个输入对象求值的脚本块({ ... }
)),根据属性名称列表对输入对象进行分组。$_.psobject.Properties.Name
生成所有属性名称的数组,"$(...)"
将其转换为空格分隔的列表。ForEach-Object
处理每个组,将每个组的第一个示例($_.Group[0]
)直接传递给Get-Member
Get-Member
调用产生单独的Display输出,使用Out-Host
;如果没有它,Display输出将错误地建议包含所有不同类型的属性的单个输入类型。如果您只对所有输入对象的不同*属性名称列表感兴趣**:
至于你的症状:
请注意,您的第一个
Get-Member
输出块提到了一个不同类型名称:Selected.System.Management.Automation.PSCustomObject
Selected.
前缀表示对象是通过Select-Object
cmdlet创建的。虽然这样的对象在技术上也是[pscustomobject]
示例,但修改后的类型名称会导致Get-Member
将其视为不同的类型。下面是一个简化的例子:
这会产生以下结果;请注意,属性是如何相同的,而只有类型名称不同:
但是,请注意,就像所有类型名为
System.Management.Automation.PSCustomObject
的[pscustomobject]
示例一样,即使具有不同的属性,所有类型名为Selected.System.Management.Automation.PSCustomObject
的示例也是如此。也就是说,由于共享相同的固定类型名称,Select-Object
创建的[pscustomobject]
示例也将被同等对待。[1]例如,
1, 2, 3 | Get-Member
只列出一个类型,System.Int32
,因为所有输入对象都具有该类型;相比之下,1, 'foo', 2 | Get-Member
列出两个类型,System.Int32
和System.String
(但不是System.Int32
Again)。[2]分配任意类型名称的功能是PowerShell ETS(扩展类型系统)的一部分-请参阅about_types.ps1xml