简短的回答:
这是 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 ,当使用-AsJob和ComputerName调用时,它在远程计算机上运行;Test-Connection ,在使用-AsJob调用时始终在本地运行(-ComputerName指定要 ping 哪台计算机,而不是在哪里运行命令);和Get-ChildItem,它没有-AsJob参数。我在远程计算机和本地计算机上都使用Start-Job、Invoke-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 不会这样做,并且该属性是只读的。