7

我在 Powershell 中创建了一个简单的后台作业:

Start-Job {"Hello"}

我检查 Get-Job:

    Id        Name         State         HasMoreData      Location       Command
    --        ----         -----         -----------      --------       -------
    1         Job1         Completed     True             localhost      "Hello"

接下来,我只是接收输出,然后再次运行 Get-Job

Receive-Job 1
Get-Job

我可以看到“HasMoreData”现在是假的,因为我没有指定-keep参数。

但是:似乎每当我开始工作时,而不是使用Start-Jobor Invoke-Command,这个“HasMoreData”参数不会更改为 False。

例子:

Get-WMIObject win32_bios -AsJob
Test-Connection . -AsJob

我可以绕过这个(错误的)行为,以便属性 HasMoreData 切换为 False,除非我指定-keep

谢谢!

更新:它似乎适用于使用该-AsJob参数进行的所有调用。如果你跑

Start-Job {Test-Connection .}

它有效(“HasMoreData”在之后变为 False Receive-Job),但是

Test-Connection . -AsJob

才不是。

4

2 回答 2

4

简短的回答:

这是 PowerShell 2.0 中的一个错误。

这对 Blaine 来说很好用,因为他使用的是 PowerShell 3,我会花钱买它。


长答案:

Start-Job cmdlet 和-AsJob开关的工作方式不同。文档通常解释说Start-Job旨在在本地运行后台作业,而-AsJob旨在使用在远程计算机上运行但在本地创建作业对象的命令启动作业。虽然这通常是正确的,但 -AsJob也可用于在本地运行作业,并且根据命令,它有时甚至无法在远程计算机上运行命令。例如,使用-AsJob-ComputerName调用的Get-WMIObject在指定的远程计算机上运行命令,而使用调用的Test-Connection-AsJob-Computername在本地运行命令并 ping 指定的计算机。

我还看到了解释Start-Job由本地 IPC 工作的文档,而-AsJob连接到指定计算机的 WinRM 服务,即使它是 localhost,并且必须在本地和目标计算机上启用 PSRemoting (s)。同样,这并不是那么简单。我发现我可以使用本地主机上的-AsJob开关运行作业,同时禁用 WinRM 和 PSRemoting。

在任何情况下,PowerShell 都会将作业作为两种 JobType(PSWmiJob 或 PSRemotingJob)之一启动。这是违反直觉的,因为在本地运行后台作业的 Start-Job总是创建一个 PSRemotingJob,而-AsJob通常创建一个 PSWmiJob,除非它与Invoke-Command一起使用,它总是启动一个 PSRemoting 作业,而不管命令是否在远程计算机或本地主机上调用。

看看下面的会话记录,我在其中以不同的方式创建了工作。我使用三个命令进行了测试:Get-WMIObject ,当使用-AsJobComputerName调用时,它在远程计算机上运行;Test-Connection ,在使用-AsJob调用时始终在本地运行(-ComputerName指定要 ping 哪台计算机,而不是在哪里运行命令);和Get-ChildItem,它没有-AsJob参数。我在远程计算机和本地计算机上都使用Start-JobInvoke-Command -AsJob和本机-AsJob为每个人开始工作开关(对于有它的命令)。

| %{$_.Name = '<the command preceding the pipe symbol>'}每个命令末尾的的目的是将每个作业命名为创建它的命令,因此在输出中更容易看到哪个作业对应于每个命令。它对作业的操作没有影响,它只是在创建每个作业后立即将其重命名为更有意义的名称。

您将看到的是,在收到所有作业后(rcjb * 2>&1|Out-Null一次接收所有作业并抑制输出),PSRemotingJob 对象的 HasMoreData 属性设置为 False,无论它们是由Start-Job还是-AsJob创建的,但 HasMoreData 属性PSWmiJob 对象的数量保持为 True。除了我在这里复制的示例之外,我发现这始终适用。

07-17-13 19:44:56.30 C:\Users\ainbar» Invoke-Command -ComputerName . -ScriptBlock {Get-WMIObject win32_bios} -AsJob | %{$_.Name = 'Invoke-Command -ComputerName . -ScriptBlock {Get-WMIObject win32_bios} -AsJob'}
07-17-13 19:44:56.43 C:\Users\ainbar» Invoke-Command -ComputerName ai8460p -ScriptBlock {Get-WMIObject win32_bios} -AsJob | %{$_.Name = 'Invoke-Command -ComputerName ai8460p -ScriptBlock {Get-WMIObject win32_bios} -AsJob'}
07-17-13 19:44:56.46 C:\Users\ainbar» Start-Job -ScriptBlock {Test-Connection .} | %{$_.Name = 'Start-Job -ScriptBlock {Test-Connection .}'}
07-17-13 19:44:57.13 C:\Users\ainbar» Test-Connection . -AsJob | %{$_.Name = 'Test-Connection . -AsJob '}
07-17-13 19:44:57.14 C:\Users\ainbar» Invoke-Command -ComputerName . -ScriptBlock {Test-Connection .} -AsJob | %{$_.Name = 'Invoke-Command -ComputerName . -ScriptBlock {Test-Connection .}'}
07-17-13 19:44:57.18 C:\Users\ainbar» Invoke-Command -ComputerName ai8460p -ScriptBlock {Test-Connection .} -AsJob | %{$_.Name = 'Invoke-Command -ComputerName ai8460p -ScriptBlock {Test-Connection .} -AsJob'}
07-17-13 19:44:57.20 C:\Users\ainbar» Start-Job -ScriptBlock {Get-ChildItem C:\} | %{$_.Name = 'Start-Job -ScriptBlock {Get-ChildItem C:\}'}
07-17-13 19:44:57.80 C:\Users\ainbar» Invoke-Command -ComputerName . -ScriptBlock {Get-ChildItem C:\} -AsJob | %{$_.Name = 'Invoke-Command -ComputerName . -ScriptBlock {Get-ChildItem C:\} -AsJob'}
07-17-13 19:44:57.82 C:\Users\ainbar» Invoke-Command -ComputerName ai8460p -ScriptBlock {Get-ChildItem C:\} -AsJob | %{$_.Name = 'Invoke-Command -ComputerName ai8460p -ScriptBlock {Get-ChildItem C:\} -AsJob'}
07-17-13 19:44:57.84 C:\Users\ainbar» $fmt_gjb = 'Id','Name','Location',@{l="JobType";e={$_.GetType().name}},@{l='HasMoreData';e={"$($_.HasMoreData)"}},'State','Command'
07-17-13 19:46:21.36 C:\Users\ainbar» gjb|ft -a $fmt_gjb

Id Name                                                                                  Location  JobType       HasMoreData     State Command
-- ----                                                                                  --------  -------       -----------     ----- -------
 1 Start-Job -ScriptBlock {Get-WMIObject win32_bios}                                     localhost PSRemotingJob True        Completed Get-WMIObject win32_bios
 3 Get-WMIObject win32_bios -AsJob                                                       localhost PSWmiJob      True        Completed Get-WMIObject
 5 Get-WMIObject win32_bios -AsJob -ComputerName ai8460p                                 ai8460p   PSWmiJob      True        Completed Get-WMIObject
 7 Invoke-Command -ComputerName . -ScriptBlock {Get-WMIObject win32_bios} -AsJob         localhost PSRemotingJob True        Completed Get-WMIObject win32_bios
 9 Invoke-Command -ComputerName ai8460p -ScriptBlock {Get-WMIObject win32_bios} -AsJob   ai8460p   PSRemotingJob True        Completed Get-WMIObject win32_bios
11 Start-Job -ScriptBlock {Test-Connection .}                                            localhost PSRemotingJob True        Completed Test-Connection .
13 Test-Connection . -AsJob                                                              .         PSWmiJob      True        Completed Test-Connection
15 Invoke-Command -ComputerName . -ScriptBlock {Test-Connection .}                       localhost PSRemotingJob True        Completed Test-Connection .
17 Invoke-Command -ComputerName ai8460p -ScriptBlock {Test-Connection .} -AsJob          ai8460p   PSRemotingJob True        Completed Test-Connection .
19 Start-Job -ScriptBlock {Get-ChildItem C:\}                                            localhost PSRemotingJob True        Completed Get-ChildItem C:\
21 Invoke-Command -ComputerName . -ScriptBlock {Get-ChildItem C:\} -AsJob                localhost PSRemotingJob True        Completed Get-ChildItem C:\
23 Invoke-Command -ComputerName ai8460p   -ScriptBlock {Get-ChildItem C:\} -AsJob        ai8460p   PSRemotingJob True        Completed Get-ChildItem C:\


07-17-13 19:46:37.94 C:\Users\ainbar» rcjb * 2>&1|Out-Null
07-17-13 19:47:14.52 C:\Users\ainbar» gjb|ft -a $fmt_gjb

Id Name                                                                                  Location  JobType       HasMoreData     State Command
-- ----                                                                                  --------  -------       -----------     ----- -------
 1 Start-Job -ScriptBlock {Get-WMIObject win32_bios}                                     localhost PSRemotingJob False       Completed Get-WMIObject win32_bios
 3 Get-WMIObject win32_bios -AsJob                                                       localhost PSWmiJob      True        Completed Get-WMIObject
 5 Get-WMIObject win32_bios -AsJob -ComputerName ai8460p                                 ai8460p   PSWmiJob      True        Completed Get-WMIObject
 7 Invoke-Command -ComputerName . -ScriptBlock {Get-WMIObject win32_bios} -AsJob         localhost PSRemotingJob False       Completed Get-WMIObject win32_bios
 9 Invoke-Command -ComputerName ai8460p -ScriptBlock {Get-WMIObject win32_bios} -AsJob   ai8460p   PSRemotingJob False       Completed Get-WMIObject win32_bios
11 Start-Job -ScriptBlock {Test-Connection .}                                            localhost PSRemotingJob False       Completed Test-Connection .
13 Test-Connection . -AsJob                                                              .         PSWmiJob      True        Completed Test-Connection
15 Invoke-Command -ComputerName . -ScriptBlock {Test-Connection .}                       localhost PSRemotingJob False       Completed Test-Connection .
17 Invoke-Command -ComputerName ai8460p -ScriptBlock {Test-Connection .} -AsJob          ai8460p   PSRemotingJob False       Completed Test-Connection .
19 Start-Job -ScriptBlock {Get-ChildItem C:\}                                            localhost PSRemotingJob False       Completed Get-ChildItem C:\
21 Invoke-Command -ComputerName . -ScriptBlock {Get-ChildItem C:\} -AsJob                localhost PSRemotingJob False       Completed Get-ChildItem C:\
23 Invoke-Command -ComputerName ai8460p   -ScriptBlock {Get-ChildItem C:\} -AsJob        ai8460p   PSRemotingJob False       Completed Get-ChildItem C:\


07-17-13 19:47:35.29 C:\Users\ainbar»

底线:错误在 PSWmiJob 对象中。无论以何种方式创建作业,也无论命令是在本地运行还是远程运行,在接收作业之后,如果 JobType 为 PSRemotingJob,则 HasMoreData 属性设置为 False,但如果 JobType 为 PSWmiJob,则保持 True。

据我所知,没有办法在 PSWmiJob 上将 HasMoreData 设置为 False。Stop-Job不会这样做,重新启动 WinRM 不会这样做,并且该属性是只读的。

于 2013-07-18T00:57:56.043 回答
1

看到这个输出:

PS C:\dell> Test-Connection . -AsJob

Id     Name            PSJobTypeName   State         HasMoreData     Location             Command
--     ----            -------------   -----         -----------     --------             -------
2      Job2            WmiJob          Running       True            .                    Test-Connection


PS C:\dell> Get-Job

Id     Name            PSJobTypeName   State         HasMoreData     Location             Command
--     ----            -------------   -----         -----------     --------             -------
2      Job2            WmiJob          Completed     True            .                    Test-Connection


PS C:\dell> Get-Job Job2 | fl


StatusMessage :
HasMoreData   : True
Location      : .
Command       : Test-Connection
JobStateInfo  : Completed
Finished      : System.Threading.ManualResetEvent
InstanceId    : d16afbe0-31f7-4189-8d2a-30ede40645c4
Id            : 2
Name          : Job2
ChildJobs     : {Job3}
PSBeginTime   : 7/16/2013 10:22:58 PM
PSEndTime     : 7/16/2013 10:22:58 PM
PSJobTypeName : WmiJob
Output        : {}
Error         : {}
Progress      : {}
Verbose       : {}
Debug         : {}
Warning       : {}
State         : Completed



PS C:\dell> Get-Job Job3

Id     Name            PSJobTypeName   State         HasMoreData     Location             Command
--     ----            -------------   -----         -----------     --------             -------
3      Job3                            Completed     True            .


PS C:\dell> Get-Job Job3 | Receive-Job

Source        Destination     IPV4Address      IPV6Address                              Bytes    Time(ms)
------        -----------     -----------      -----------                              -----    --------
W4-G9W... localhost       127.0.0.1                                                 32       0
W4-G9W... localhost       127.0.0.1                                                 32       0
W4-G9W... localhost       127.0.0.1                                                 32       0
W4-G9W... localhost       127.0.0.1                                                 32       0


PS C:\dell> Get-Job Job2 | fl


StatusMessage :
HasMoreData   : False
Location      : .
Command       : Test-Connection
JobStateInfo  : Completed
Finished      : System.Threading.ManualResetEvent
InstanceId    : d16afbe0-31f7-4189-8d2a-30ede40645c4
Id            : 2
Name          : Job2
ChildJobs     : {Job3}
PSBeginTime   : 7/16/2013 10:22:58 PM
PSEndTime     : 7/16/2013 10:22:58 PM
PSJobTypeName : WmiJob
Output        : {}
Error         : {}
Progress      : {}
Verbose       : {}
Debug         : {}
Warning       : {}
State         : Completed



PS C:\dell> Get-Job Job3

Id     Name            PSJobTypeName   State         HasMoreData     Location             Command
--     ----            -------------   -----         -----------     --------             -------
3      Job3                            Completed     False           .

您会看到 Job2 是顶级作业,它创建了一个名为 Job3 的子作业。这就是实际行动发生的地方。

您能否接收子作业并检查 HasMoreData 是否仍设置?

于 2013-07-16T16:57:37.197 回答