我在PowerShell 5.0中使用作业时发现了奇怪的行为。
返回PSObject
的运行作业也会返回一些哈希表。
返回字符串,整数等的作业很有效。
运行
Start-Job { New-Object PSObject -Property @{ A = 1 } } |
Receive-Job -Wait -AutoRemoveJob
返回
A : 1 RunspaceId : 6921e85f-301e-4e95-8e4b-c0882fc2085f PSSourceJobInstanceId : 2992ef77-5642-4eac-8617-f26449a87801
运行
Start-Job { New-Object PSObject } | Receive-Job -Wait -AutoRemoveJob
返回
@{PSComputerName=localhost; RunspaceId=3e783d5f-254a-4951-bb4a-7ff6fa2812c5; PSShowComputerName=False; PSSourceJobInstanceId=1d951dec-0823-4cde-8219-4a6263550441}
然而,正在运行
Start-Job { ,@(New-Object PSObject -Property @{ A = 1 }) } |
Receive-Job -Wait -AutoRemoveJob
返回
A - 1
为什么Receive-Job
cmdlet仅为PSObject
添加该哈希表?
更新:与PowerShell 4.0相同。
答案 0 :(得分:3)
PowerShell不是WYSIWYG shell。通常,“你得到的”不是文本,而是具有属性和方法的对象。而“你所看到的”是他们的一些文字表示。在许多情况下,默认情况下,PowerShell不显示所有对象的属性,而只显示格式文件中定义的最常见属性。有些对象使用自定义格式,比如字符串和整数只显示它们的值,但不显示它的任何属性,集合显示其内容但不显示集合本身。
因此,事实上,PowerShell为从作业接收的所有对象添加了额外的属性。但是这些属性并不总是显示出来。您可以通过将作业输出传递给Get-Member
cmdlet:
Start-Job { 1,'',@() } | Receive-Job -Wait -AutoRemoveJob | Get-Member
或使用适当的选项格式化cmdlet以强制格式化基元类型并且不枚举集合:
Start-Job { 1,'',@() } | Receive-Job -Wait -AutoRemoveJob | Format-List -Force -Expand CoreOnly
答案 1 :(得分:2)
补充 PetSerAl's excellent answer,专注于哈希表 (哈希表),基于PetSerAl的有用评论:
Start-Job { New-Object PSObject } | Receive-Job -Wait -AutoRemoveJob
的输出,
@{PSComputerName=localhost; RunspaceId=3e783d5f-254a-4951-bb4a-7ff6fa2812c5; PSShowComputerName=False; PSSourceJobInstanceId=1d951dec-0823-4cde-8219-4a6263550441}
只有看起来像一样哈希表文字;实际上,它是"无属性"的默认输出格式。 自定义对象实际上做具有属性,但仅由PowerShell自身添加 。
这种表示与哈希表文字很可疑相似,但缺少通常需要它的值的引用 - 例如localhost
左右。
另请注意,输出实际哈希表会产生更好的双列键值格式。
请注意,即使PS本身已向其添加了属性,PS仍然认为最初没有属性的自定义对象,例如Receive-Job
此处 - 请参阅下面的详细信息
在其原始状态(尚未添加PS的属性)中,无属性对象的默认输出为空(空字符串)。(请在提示时直接尝试New-Object PSCustomObject
。)
Receive-Job
添加了" meta"自定义对象的属性,它们的存在会触发散列表 - ,如输出格式。
PetSerAl提供了source code的链接,这表明" PropertyLessObject"在以下条件下触发格式化:
对象根本没有属性,或者只有PowerShell在远程处理的上下文中自动添加属性(显然还包括作业相关的cmdlet) ,由Receive-Object
在这里完成。
换句话说:在决定对象是否无财产时,不会考虑PS自动添加的属性。
源代码链接将告诉您在远程处理期间可能添加的特定的3,4或5个元素的远程处理属性并触发格式化,但这里是最小的(3个属性)例如,
同样,请注意,仅触发类似哈希表的格式化,因为对象具有的唯一属性是为与远程处理相关的自动添加的属性命名的:
> [PSCustomObject] @{PSComputerName='Hi, Mom'; RunspaceId=0; PSShowComputerName=$false}
@{PSComputerName=Hi, Mom; RunspaceId=0; PSShowComputerName=False}
请注意,即使命令中的哈希表文字涉及,它也仅用于构造自定义对象。
您可以强制使用Format-List -Force
或Format-Table -Force
的正常列表或表格视图,但请注意,布尔属性PSShowComputerName
永远不会显示并隐式控制关联的 PSComputerName
属性是否包含在列表/表中。
PetSerAl还指出,您可以为任何自定义对象获取 输出格式 :只需调用 .PSObject.ToString()
(请注意关键的.PSObject
部分;如果没有它,则会得到空输出。)
> ([pscustomobject] @{ one = 'Hi, Mom'; two = 2 }).PSObject.ToString()
@{one=Hi, Mom; two=2}
或者更简单地说,使用字符串插值(可能只是在幕后调用.PSObject.ToString()
):
> "$([pscustomobject] @{ one = 'Hi, Mom'; two = 2 })"
@{one=Hi, Mom; two=2}
请注意,此 不适用于任何其他类型的实例(对象不派生自[System.Management.Automation.PSObject]
):
即使您调用.ToString()
,PowerShell仍会使用.PSObject.ToString()
方法。
默认情况下,直接基于.NET的类型(例如,添加Add-Type
)只返回其完整类型名称(均来自.ToString()
/ { {1}}和PS中的默认输出; e.g:
.PSObject.ToString()