Powershell 接收作业中未预期的结果
在PowerShell 5.0中使用作业时,我注意到了奇怪的行为。 运行返回Powershell 接收作业中未预期的结果,powershell,jobs,psobject,Powershell,Jobs,Psobject,在PowerShell 5.0中使用作业时,我注意到了奇怪的行为。 运行返回PSObject的作业时,也会返回一些哈希表。 返回字符串、整数等的作业工作正常 运行 Start-Job { New-Object PSObject -Property @{ A = 1 } } | Receive-Job -Wait -AutoRemoveJob Start-Job { New-Object PSObject } | Receive-Job -Wait -AutoRemoveJob 返回 A
PSObject
的作业时,也会返回一些哈希表。
返回字符串、整数等的作业工作正常
运行
Start-Job { New-Object PSObject -Property @{ A = 1 } } |
Receive-Job -Wait -AutoRemoveJob
Start-Job { New-Object PSObject } | Receive-Job -Wait -AutoRemoveJob
返回
A : 1
RunspaceId : 6921e85f-301e-4e95-8e4b-c0882fc2085f
PSSourceJobInstanceId : 2992ef77-5642-4eac-8617-f26449a87801
@{PSComputerName=localhost; RunspaceId=3e783d5f-254a-4951-bb4a-7ff6fa2812c5; PSShowComputerName=False; PSSourceJobInstanceId=1d951dec-0823-4cde-8219-4a6263550441}
A
-
1
返回
A : 1
RunspaceId : 6921e85f-301e-4e95-8e4b-c0882fc2085f
PSSourceJobInstanceId : 2992ef77-5642-4eac-8617-f26449a87801
@{PSComputerName=localhost; RunspaceId=3e783d5f-254a-4951-bb4a-7ff6fa2812c5; PSShowComputerName=False; PSSourceJobInstanceId=1d951dec-0823-4cde-8219-4a6263550441}
A
-
1
返回
A : 1
RunspaceId : 6921e85f-301e-4e95-8e4b-c0882fc2085f
PSSourceJobInstanceId : 2992ef77-5642-4eac-8617-f26449a87801
@{PSComputerName=localhost; RunspaceId=3e783d5f-254a-4951-bb4a-7ff6fa2812c5; PSShowComputerName=False; PSSourceJobInstanceId=1d951dec-0823-4cde-8219-4a6263550441}
A
-
1
A.
-
1.
为什么Receive Job
cmdlet只为PSObject
s添加该哈希表
更新:与PowerShell 4.0相同。PowerShell不是所见即所得的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
根据PetSerAl的有用评论,将注意力集中在非哈希表(哈希表)上,作为补充:
Start Job{New Object PSObject}接收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尚未添加属性),无属性对象的默认输出为空(空字符串)。(直接在提示下尝试新建对象PSCustomObject
)
一旦Receive Job
将其“meta”属性添加到自定义对象,它们的存在将触发类似哈希表的输出格式设置。
PetSerAl提供了指向的链接,这表明在以下条件下触发了“PropertyLessObject”格式设置:
- 对象完全没有属性,或者只有PowerShell在远程处理上下文中自动添加的属性(显然还包括与作业相关的cmdlet),就像这里的
所做的那样Receive object
- 换言之:在确定对象是否为无属性时,不考虑PS自动添加的属性
再次请注意,之所以会触发类似哈希表的格式设置,是因为对象仅有的属性是为远程处理相关的自动添加属性命名的:
PS> [PSCustomObject] @{PSComputerName='Hi, Mom'; RunspaceId=0; PSShowComputerName=$true}
@{PSComputerName=Hi, Mom; RunspaceId=0; PSShowComputerName=False}
请注意,尽管命令中涉及哈希表文字,但它仅用于构造自定义对象
您可以使用Format list-force
或Format table-force
强制普通列表或表视图,但请注意,布尔属性PSShowComputerName
从不显示,而是隐式控制关联的PSComputerName
属性是否包含在列表/表中
PetSerAl还指出,您可以根据需要为任何自定义对象获取类似哈希表的输出格式:只需调用
.PSObject.ToString()
(请注意关键的.PSObject
部分;没有它,您将获得空输出)
或者,更简单地说,使用字符串插值(可能只是在幕后调用.PSObject.ToString()
):
请注意,这种字符串插值不适用于任何其他类型的实例(不是类型[System.Management.Automation.PSCustomObject]
):
- 即使在调用
时,PowerShell也会遵从它们的.PSObject.ToString()
方法.ToString()
- 默认情况下,直接基于.NET的类型(例如,添加了
)只返回其完整类型名(来自Add type
/.ToString()
,并作为PS中的默认输出);e、 g:.PSObject.ToString()
- 这同样适用于自定义PowerShell类的实例(用
定义)类{…}
Start Job{[PSCustomObject]@{A=1}}| Receive Job-Wait-AutoRemoveJob
@PetSerAl,我没有意识到它还向整数和字符串添加注释属性。你能写下来作为答案吗?@PetSerAl:很好的建议,谢谢。但是,我认为没有调用.ToString()
(至少不是直接在对象上),有3组3-5个远程处理相关属性触发了这种格式设置(如果它们是唯一的属性的话)。我已经发布了我的发现作为答案-如果我有什么错误,请让我知道。@PetSerAl:明白了,再次感谢;.PSObject.ToString()
的.PSObject
部分是缺少的拼图块-答案已更新。(如果有的话