PowerShell Add-Member ...奇怪的行为?
Posted
技术标签:
【中文标题】PowerShell Add-Member ...奇怪的行为?【英文标题】:PowerShell Add-Member ... odd behaviour? 【发布时间】:2021-10-02 13:33:31 【问题描述】:谁能解释使用 Add-Member 向 PSCustomObject 对象添加属性时出现的奇怪行为?出于某种原因,一旦您添加了成员,该对象在显示时就会像 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 表示,如以下示例所示:
[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和powershell ise到底分别干啥用,powershell命令那么长怎么记
powershell PowerShell:启动PowerShell作为其他用户提升