接收作业中出现意外结果 [英] Unexected results in Receive-Job
问题描述
在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
s添加该哈希表?
更新:在PowerShell 4.0中相同.
为补充 PetSerAl的出色答案基于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}
仅看起来像哈希表文字;实际上,这是无属性" 自定义对象的默认输出格式,实际上, do 具有属性,但仅添加了由PowerShell本身 .
该表示形式与哈希表文字可疑地相似,但是缺少通常需要它的值的引号-例如localhost
周围.
另外请注意,输出 actual 哈希表会产生更好的两列键值格式.
请注意,即使PS本身已向其添加属性(例如,按Receive-Job
的方式,请参见此处,详情如下),PS仍会认为自定义对象最初没有属性缺乏属性. /p>
在原始状态(PS尚未添加任何属性),无属性对象的默认输出为 empty (空字符串).(尝试New-Object PSCustomObject
直接在提示下.)
Receive-Job
一旦将其"meta"属性添加到自定义对象,它们的存在就会触发哈希表,类似于 的输出格式.
PetSerAl提供了指向:>
一个对象完全没有属性,或者只有PowerShell在 remoting (显然还包括与 job 相关的cmdlet)上下文中自动添加的属性. ,如 换句话说:在确定对象是否为无属性时,不会考虑PS自动添加的属性. 源代码链接将告诉您可以在远程处理期间添加并触发格式化的特定的3,4或5元素远程处理属性集,但这是一个最小的(3个属性)示例. br>
同样,请注意,仅会触发类似哈希表的格式,因为对象具有的唯一属性是为与远程相关的自动添加的属性命名的: 请注意,即使命令中包含哈希表文字 ,它也仅用于构造自定义对象. 您可以使用 PetSerAl还指出,您可以为任何自定义对象按需获取类似哈希表的 输出格式 只需调用 或更简单地说,使用字符串插值(大概只是在幕后调用 请注意,这种字符串内插对其他任何类型的实例(类型为 PowerShell遵循它们的 默认情况下,直接基于.NET的类型(例如,添加了 这同样适用于自定义PowerShell类(用 I noticed weird behavior when using jobs in PowerShell 5.0.
Running job that returns Running returns Running returns However, running returns Why does UPDATE: Same in PowerShell 4.0. To complement PetSerAl's excellent answer with a focus on the hashtable that wasn't (a hashtable), based on PetSerAl's helpful comments: The output from only looks like a hashtable literal; in fact, it is the default output formatting for "property-less" custom objects that, in fact, do have properties, but only ones added by PowerShell itself. This representation is suspiciously similar to a hashtable literal, but the quoting around values that would normally need it is missing - such as around Note that PS still considers a custom object that originally had no properties property-less even after PS itself has added properties to it, such as by In its original state (no properties added by PS yet), a property-less object's default output is empty (the empty string). (Try Once PetSerAl has provided a link to the source code, which suggests that the "PropertyLessObject" formatting is triggered under the following conditions: An object has no properties at all or only has properties automatically added by PowerShell in the context of remoting (which apparently also includes job-related cmdlets), as done by To put it differently: Properties automatically added by PS aren't taken into account when deciding whether an object is propertyless. The source-code link will tell you the specific 3-, 4-, or 5-element sets of remoting properties that may be added during remoting and trigger the formatting, but here's a minimal (3-property) example. Note that even though a hashtable literal is involved in the command, it is merely used to construct a custom object. You can force a normal list or table view with PetSerAl also points out that you can get the hashtable-like output format on demand for any custom object: simply invoke Or, more simply, with string interpolation (which, presumably, simply calls Note that this kind of string interpolation does not work for instances of any other types (objects not of type PowerShell defers to their A directly .NET-based type (e.g., as added with The same applies to instances of custom PowerShell classes (defined with 这篇关于接收作业中出现意外结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
Receive-Object
此处所做的.PS> [PSCustomObject] @{PSComputerName='Hi, Mom'; RunspaceId=0; PSShowComputerName=$true}
@{PSComputerName=Hi, Mom; RunspaceId=0; PSShowComputerName=False}
Format-List -Force
或Format-Table -Force
强制普通列表或表格视图,但请注意,布尔属性PSShowComputerName
从不出现,而是隐式控制关联 PSComputerName
属性是否包含在列表/表中.
.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]
的对象 not ) not 不起作用:
.ToString()
方法,即使您调用.PSObject.ToString()
.Add-Type
)仅返回其完整类型名称(均来自.ToString()
/.PSObject.ToString()
, PS中的默认输出);例如:PS> (Add-Type -PassThru 'namespace net.same2u { public class SomeType {} }')::New()
net.same2u.SomeType # the full type name
class { ... }
定义)的实例.PSObject
, also returns some hashtable.
Jobs that return strings, integers, etc work propertly.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 add that hashtable only for PSObject
s?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}
localhost
.
Also note that outputting an actual hashtable results in a much nicer, two-column key-value format.Receive-Job
here - see below for details.New-Object PSCustomObject
directly at the prompt.)Receive-Job
has added its "meta" properties to the custom object, their existence triggers the hashtable-like output formatting.
Receive-Object
here.
Again, note that the hashtable-like formatting is only triggered because the only properties that the object has are named for remoting-related, automatically added properties:PS> [PSCustomObject] @{PSComputerName='Hi, Mom'; RunspaceId=0; PSShowComputerName=$true}
@{PSComputerName=Hi, Mom; RunspaceId=0; PSShowComputerName=False}
Format-List -Force
or Format-Table -Force
, but note that Boolean property PSShowComputerName
never shows up and instead implicitly controls whether the associated PSComputerName
property is included in the list / table.
.PSObject.ToString()
(note the crucial .PSObject
part; without it, you get empty output).PS> ([pscustomobject] @{ one = 'Hi, Mom'; two = 2 }).PSObject.ToString()
@{one=Hi, Mom; two=2}
.PSObject.ToString()
behind the scenes):PS> "$([pscustomobject] @{ one = 'Hi, Mom'; two = 2 })"
@{one=Hi, Mom; two=2}
[System.Management.Automation.PSCustomObject]
):
.ToString()
method even when you invoke .PSObject.ToString()
.Add-Type
) by default simply returns its full type name (both from .ToString()
/ .PSObject.ToString()
and as default output in PS); e.g.:PS> (Add-Type -PassThru 'namespace net.same2u { public class SomeType {} }')::New()
net.same2u.SomeType # the full type name
class { ... }
).