【问题标题】:Unexected results in Receive-JobReceive-Job 中的意外结果
【发布时间】:2017-03-03 14:25:45
【问题描述】:

我注意到在 PowerShell 5.0 中使用作业时出现了奇怪的行为。 运行返回PSObject 的作业也返回一些哈希表。 返回字符串、整数等的作业可以正常工作。

跑步

Start-Job { New-Object PSObject -Property @{ A = 1 } } |
  Receive-Job -Wait -AutoRemoveJob

返回

一:1
运行空间 ID:6921e85f-301e-4e95-8e4b-c0882fc2085f
PSSourceJobInstanceId : 2992ef77-5642-4eac-8617-f26449a87801

跑步

Start-Job { New-Object PSObject } | Receive-Job -Wait -AutoRemoveJob

返回

@{PSComputerName=localhost;运行空间 ID=3e783d5f-254a-4951-bb4a-7ff6fa2812c5; PSShowComputerName=假; PSSourceJobInstanceId=1d951dec-0823-4cde-8219-4a6263550441}

但是,正在运行

Start-Job { ,@(New-Object PSObject -Property @{ A = 1 }) } |
  Receive-Job -Wait -AutoRemoveJob

返回

一个
-
1

为什么Receive-Job cmdlet 只为PSObjects 添加该哈希表?

更新:在 PowerShell 4.0 中相同。

【问题讨论】:

  • FWIW,它对 PSCustomObject 的行为相同:Start-Job { [PSCustomObject]@{A=1} } | Receive-Job -Wait -AutoRemoveJob
  • @PetSerAl,我没有意识到它还会为整数和字符串添加注释属性。你能把它写成答案吗?
  • @PetSerAl:很好的指点,谢谢。但是,我不认为 .ToString() 被调用(至少不是直接在对象上),并且有 3 组 3-5 个与远程处理相关的属性会触发这种格式(如果它们是唯一的属性)。我已经发布了我的发现作为答案 - 如果我有什么问题,请在那里告诉我。
  • @PetSerAl:知道了,再次感谢; .PSObject.ToString().PSObject 部分是缺失的拼图 - 答案已更新。 (如果有什么要补充/更正的,请评论那里)。
  • 如果某个答案解决了您的问题,请点击旁边的大复选标记 (✓) 接受它,并可选择对其进行投票(投票至少需要 15 个声望点)。如果您发现其他答案有帮助,请给他们投票。接受和投票有助于未来的读者。请参阅the relevant help-center article。如果您的问题尚未完全得到解答,请提供反馈。如果您认为自己找到了最佳解决方案,请将其发布为答案并自我接受。

标签: powershell jobs psobject


【解决方案1】:

PowerShell 不是所见即所得的外壳。通常,“你得到什么”不是文本,而是具有属性和方法的对象。而“你所看到的”是它们的一些文本表示。在许多情况下,默认情况下,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

【讨论】:

    【解决方案2】:

    补充 PetSerAl's excellent answer 专注于不是的哈希表(哈希表),基于 PetSerAl 的有用 cmets:

    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 尚未添加任何属性),无属性对象的默认输出是empty(空字符串)。(试试New-Object PSCustomObject直接在提示符下。)

    一旦Receive-Job 将其“元”属性添加到自定义对象,它们的存在就会触发散列表类似的输出格式。


    PetSerAl 提供了指向source code 的链接,这表明“PropertyLessObject”格式在以下情况下被触发

    • 一个对象根本没有属性,或者只有 PowerShell 在 remoting 上下文中自动添加的属性(显然还包括与 job 相关的 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 -ForceFormat-Table -Force强制使用普通列表或表格视图,但请注意布尔属性PSShowComputerName 从不显示,而是隐式控制关联 PSComputerName 属性是否包含在列表/表格中。


    PetSerAl 还指出,您可以为任何自定义对象按需获取哈希表-like输出格式: strong> 只需调用 .PSObject.ToString()(注意关键的 .PSObject 部分;没有它,您将得到 empty 输出)。

    PS> ([pscustomobject] @{ one = 'Hi, Mom'; two = 2 }).PSObject.ToString()
    @{one=Hi, Mom; two=2}
    

    或者,更简单地说,使用 字符串插值(大概只是在幕后调用.PSObject.ToString()):

    PS> "$([pscustomobject] @{ one = 'Hi, Mom'; two = 2 })"
    @{one=Hi, Mom; two=2}
    

    请注意,这种字符串插值适用于任何其他类型的实例(对象类型为[System.Management.Automation.PSCustomObject]

    • 即使您调用 .PSObject.ToString(),PowerShell 也会遵循他们的 .ToString() 方法。

    • 直接基于 .NET 的类型(例如,与 Add-Type 一起添加)默认只返回其完整类型名称(来自 .ToString() / .PSObject.ToString() 和作为默认输出PS);例如:

      PS> (Add-Type -PassThru 'namespace net.same2u { public class SomeType {} }')::New()
      net.same2u.SomeType  # the full type name
      
    • 这同样适用于自定义 PowerShell 类的实例(使用 class { ... } 定义)。

    【讨论】:

      猜你喜欢
      • 2020-03-29
      • 2011-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-15
      • 2012-04-02
      相关资源
      最近更新 更多