Powershell 接收作业中未预期的结果

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

在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 : 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自动添加的属性

源代码链接将告诉您在远程处理期间可能添加的特定3、4或5元素远程处理属性集,并触发格式化,但这里有一个最小的(3元素属性)示例。
再次请注意,之所以会触发类似哈希表的格式设置,是因为对象仅有的属性是为远程处理相关的自动添加属性命名的:

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]

  • 即使在调用
    .PSObject.ToString()
    时,PowerShell也会遵从它们的
    .ToString()
    方法

  • 默认情况下,直接基于.NET的类型(例如,添加了
    Add type
    )只返回其完整类型名(来自
    .ToString()
    /
    .PSObject.ToString()
    ,并作为PS中的默认输出);e、 g:

  • 这同样适用于自定义PowerShell类的实例(用
    类{…}
    定义)


FWIW,它对PSCustomObject的行为相同:
Start Job{[PSCustomObject]@{A=1}}| Receive Job-Wait-AutoRemoveJob
@PetSerAl,我没有意识到它还向整数和字符串添加注释属性。你能写下来作为答案吗?@PetSerAl:很好的建议,谢谢。但是,我认为没有调用
.ToString()
(至少不是直接在对象上),有3组3-5个远程处理相关属性触发了这种格式设置(如果它们是唯一的属性的话)。我已经发布了我的发现作为答案-如果我有什么错误,请让我知道。@PetSerAl:明白了,再次感谢;
.PSObject.ToString()
.PSObject
部分是缺少的拼图块-答案已更新。(如果有的话