PowerShell Add-Member ...奇怪的行为?

Posted

技术标签:

【中文标题】PowerShell Add-Member ...奇怪的行为?【英文标题】:PowerShell Add-Member ... odd behaviour? 【发布时间】:2021-10-02 13:33:31 【问题描述】:

谁能解释使用 Add-MemberPSCustomObject 对象添加属性时出现的奇怪行为?出于某种原因,一旦您添加了成员​​,该对象在显示时就会像 hashtable 一样表示,即使它仍然是 PSCustomObject,例如:

创建一个简单的对象:

[PSCustomObject] $test = New-Object -TypeName PSCustomObject -Property @ a = 1; b = 2; c = 3; 

检查它的类型:

$test.GetType();

...返回:

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    PSCustomObject                           System.Object

然后获取它的内容:

$test;

...返回:

c b a
- - -
3 2 1

添加属性:

Add-Member -InputObject $test -MemberType NoteProperty -Name d -Value 4 -TypeName Int32;

确认其类型没有改变:

$test.GetType();

...返回:

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    PSCustomObject                           System.Object

最后,再次获取它的内容:

$test;

...返回:

@c=3; b=2; a=1; d=4

而我希望得到:

c d b a
- - - -
3 4 2 1

欢迎任何想法,因为我多年来一直在挑选。

非常感谢

【问题讨论】:

在构造函数的哈希表中有一个分号。应该是:@ a = 1; b = 2; c = 3 还有:Avoid Using Semicolons (;) as Line Terminators PowerShell will not complain about extra semicolons, but they are unnecessary, and can get in the way when code is being edited or copy-pasted. They also result in extra do-nothing edits in source control when someone finally decides to delete them. 【参考方案1】:

Add-Member 调用中省略-TypeName Int32 参数指定-Value 参数的类型。。 p>

# Do NOT use -TypeName, unless you want to assign the custom
# object stored in $test a specific ETS type identity.
Add-Member -InputObject $test -MemberType NoteProperty -Name d -Value 4

请注意,Int32 ([int]) 是隐含用于可以解释为适合[int] 范围的十进制数的不带引号的参数,例如4

如果您确实需要明确指定类型,请在 表达式 中使用 cast,例如... -Value ([long] 4)


至于你尝试了什么

-TypeName Int32 将此类型的全名System.Int32 指定为与​​输入相关的ETS 类型名称 列表中的第一个条目对象。 (ETS 是 PowerShell 的Extended Type System。)

您可以通过访问intrinsic .pstypenames 属性查看此列表(您还可以在Get-Member 的输出标题中看到它的first 条目):

PS> $test.pstypenames

System.Int32
System.Management.Automation.PSCustomObject
System.Object

如您所见,System.Int32 被插入到对象的真实 .NET 类型标识 (System.Management.Automation.PSCustomObject) 之前;其余条目显示继承层次结构。

此类ETS 类型名称通常用于将自定义行为与对象相关联,无论它们的真实 .NET 类型标识如何,尤其是关于扩展类型(参见about_Types.ps1xml)或自定义显示格式与其关联(参见about_Format.ps1xml)。

由于 PowerShell 认为您的 [pscustomobject][int] (System.Int32) 类型,因此它应用了该类型的常用输出格式,这实质上意味着在实例上调用 .ToString()

[pscustomobject] 实例上调用.ToString() 会产生您看到的哈希表like 表示,如以下示例所示:

注意使用 PSv3+ 语法糖 来创建 [pscustomobject] 实例 ([pscustomobject] @ ... ),这不仅比 New-Object 调用更有效,而且保留了属性顺序
PS> ([pscustomobject] @ a = 'foo bar'; b = 2).psobject.ToString()

@a=foo bar; b=2

注意使用固有的 .psobject 属性,这是解决长期存在的错误所必需的,直接 .ToString() 调用 [pscustomobject] 实例返回 空字符串 - 见GitHub issue #6163。

【讨论】:

以上是关于PowerShell Add-Member ...奇怪的行为?的主要内容,如果未能解决你的问题,请参考以下文章

Powershell 之POP3邮件管理

powershell和powershell ise到底分别干啥用,powershell命令那么长怎么记

powershell怎么运行

powershell PowerShell:启动PowerShell作为其他用户提升

powershell [提示输入powershell] #powershell #input #prompt

powershell 测量PowerShell命令或PowerShell脚本的速度