即使在Receive-Job之后,"HasMoreData"也是如此

Joo*_*ost 7 powershell jobs

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

Start-Job {"Hello"}
Run Code Online (Sandbox Code Playgroud)

我查看了Get-Job:

    Id        Name         State         HasMoreData      Location       Command
    --        ----         -----         -----------      --------       -------
    1         Job1         Completed     True             localhost      "Hello"
Run Code Online (Sandbox Code Playgroud)

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

Receive-Job 1
Get-Job
Run Code Online (Sandbox Code Playgroud)

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

但是:似乎无论什么时候我开始一个工作,而不是Start-Job或者Invoke-Command,这个"HasMoreData"参数不会改为False.

例子:

Get-WMIObject win32_bios -AsJob
Test-Connection . -AsJob
Run Code Online (Sandbox Code Playgroud)

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

谢谢!

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

Start-Job {Test-Connection .}
Run Code Online (Sandbox Code Playgroud)

它工作("HasMoreData"后变为False Receive-Job),但是

Test-Connection . -AsJob
Run Code Online (Sandbox Code Playgroud)

才不是.

Adi*_*bar 4

简短回答:

\n\n

这是 PowerShell 2.0 中的一个错误。

\n\n

它对 Blaine 来说效果很好,因为他使用的是 PowerShell 3,我愿意花钱买它。

\n\n
\n\n

长答案:

\n\n

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

\n\n

我还看到文档解释了Start-Job通过本地 IPC 工作,而-AsJob连接到指定计算机的 WinRM 服务,即使它是本地主机,并且必须在本地主机上启用 PSRemoting本地和目标计算机。再说一次,事情并不是那么简单。我发现我可以在禁用 WinRM 和 PSRemoting 的情况下在本地主机上使用-AsJob开关运行作业。

\n\n

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

\n\n

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

\n\n

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

\n\n

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

\n\n
07-17-13 19:44:56.30 C:\\Users\\ainbar\xc2\xbb Invoke-Command -ComputerName . -ScriptBlock {Get-WMIObject win32_bios} -AsJob | %{$_.Name = \'Invoke-Command -ComputerName . -ScriptBlock {Get-WMIObject win32_bios} -AsJob\'}\n07-17-13 19:44:56.43 C:\\Users\\ainbar\xc2\xbb Invoke-Command -ComputerName ai8460p -ScriptBlock {Get-WMIObject win32_bios} -AsJob | %{$_.Name = \'Invoke-Command -ComputerName ai8460p -ScriptBlock {Get-WMIObject win32_bios} -AsJob\'}\n07-17-13 19:44:56.46 C:\\Users\\ainbar\xc2\xbb Start-Job -ScriptBlock {Test-Connection .} | %{$_.Name = \'Start-Job -ScriptBlock {Test-Connection .}\'}\n07-17-13 19:44:57.13 C:\\Users\\ainbar\xc2\xbb Test-Connection . -AsJob | %{$_.Name = \'Test-Connection . -AsJob \'}\n07-17-13 19:44:57.14 C:\\Users\\ainbar\xc2\xbb Invoke-Command -ComputerName . -ScriptBlock {Test-Connection .} -AsJob | %{$_.Name = \'Invoke-Command -ComputerName . -ScriptBlock {Test-Connection .}\'}\n07-17-13 19:44:57.18 C:\\Users\\ainbar\xc2\xbb Invoke-Command -ComputerName ai8460p -ScriptBlock {Test-Connection .} -AsJob | %{$_.Name = \'Invoke-Command -ComputerName ai8460p -ScriptBlock {Test-Connection .} -AsJob\'}\n07-17-13 19:44:57.20 C:\\Users\\ainbar\xc2\xbb Start-Job -ScriptBlock {Get-ChildItem C:\\} | %{$_.Name = \'Start-Job -ScriptBlock {Get-ChildItem C:\\}\'}\n07-17-13 19:44:57.80 C:\\Users\\ainbar\xc2\xbb Invoke-Command -ComputerName . -ScriptBlock {Get-ChildItem C:\\} -AsJob | %{$_.Name = \'Invoke-Command -ComputerName . -ScriptBlock {Get-ChildItem C:\\} -AsJob\'}\n07-17-13 19:44:57.82 C:\\Users\\ainbar\xc2\xbb Invoke-Command -ComputerName ai8460p -ScriptBlock {Get-ChildItem C:\\} -AsJob | %{$_.Name = \'Invoke-Command -ComputerName ai8460p -ScriptBlock {Get-ChildItem C:\\} -AsJob\'}\n07-17-13 19:44:57.84 C:\\Users\\ainbar\xc2\xbb $fmt_gjb = \'Id\',\'Name\',\'Location\',@{l="JobType";e={$_.GetType().name}},@{l=\'HasMoreData\';e={"$($_.HasMoreData)"}},\'State\',\'Command\'\n07-17-13 19:46:21.36 C:\\Users\\ainbar\xc2\xbb gjb|ft -a $fmt_gjb\n\nId Name                                                                                  Location  JobType       HasMoreData     State Command\n-- ----                                                                                  --------  -------       -----------     ----- -------\n 1 Start-Job -ScriptBlock {Get-WMIObject win32_bios}                                     localhost PSRemotingJob True        Completed Get-WMIObject win32_bios\n 3 Get-WMIObject win32_bios -AsJob                                                       localhost PSWmiJob      True        Completed Get-WMIObject\n 5 Get-WMIObject win32_bios -AsJob -ComputerName ai8460p                                 ai8460p   PSWmiJob      True        Completed Get-WMIObject\n 7 Invoke-Command -ComputerName . -ScriptBlock {Get-WMIObject win32_bios} -AsJob         localhost PSRemotingJob True        Completed Get-WMIObject win32_bios\n 9 Invoke-Command -ComputerName ai8460p -ScriptBlock {Get-WMIObject win32_bios} -AsJob   ai8460p   PSRemotingJob True        Completed Get-WMIObject win32_bios\n11 Start-Job -ScriptBlock {Test-Connection .}                                            localhost PSRemotingJob True        Completed Test-Connection .\n13 Test-Connection . -AsJob                                                              .         PSWmiJob      True        Completed Test-Connection\n15 Invoke-Command -ComputerName . -ScriptBlock {Test-Connection .}                       localhost PSRemotingJob True        Completed Test-Connection .\n17 Invoke-Command -ComputerName ai8460p -ScriptBlock {Test-Connection .} -AsJob          ai8460p   PSRemotingJob True        Completed Test-Connection .\n19 Start-Job -ScriptBlock {Get-ChildItem C:\\}                                            localhost PSRemotingJob True        Completed Get-ChildItem C:\\\n21 Invoke-Command -ComputerName . -ScriptBlock {Get-ChildItem C:\\} -AsJob                localhost PSRemotingJob True        Completed Get-ChildItem C:\\\n23 Invoke-Command -ComputerName ai8460p   -ScriptBlock {Get-ChildItem C:\\} -AsJob        ai8460p   PSRemotingJob True        Completed Get-ChildItem C:\\\n\n\n07-17-13 19:46:37.94 C:\\Users\\ainbar\xc2\xbb rcjb * 2>&1|Out-Null\n07-17-13 19:47:14.52 C:\\Users\\ainbar\xc2\xbb gjb|ft -a $fmt_gjb\n\nId Name                                                                                  Location  JobType       HasMoreData     State Command\n-- ----                                                                                  --------  -------       -----------     ----- -------\n 1 Start-Job -ScriptBlock {Get-WMIObject win32_bios}                                     localhost PSRemotingJob False       Completed Get-WMIObject win32_bios\n 3 Get-WMIObject win32_bios -AsJob                                                       localhost PSWmiJob      True        Completed Get-WMIObject\n 5 Get-WMIObject win32_bios -AsJob -ComputerName ai8460p                                 ai8460p   PSWmiJob      True        Completed Get-WMIObject\n 7 Invoke-Command -ComputerName . -ScriptBlock {Get-WMIObject win32_bios} -AsJob         localhost PSRemotingJob False       Completed Get-WMIObject win32_bios\n 9 Invoke-Command -ComputerName ai8460p -ScriptBlock {Get-WMIObject win32_bios} -AsJob   ai8460p   PSRemotingJob False       Completed Get-WMIObject win32_bios\n11 Start-Job -ScriptBlock {Test-Connection .}                                            localhost PSRemotingJob False       Completed Test-Connection .\n13 Test-Connection . -AsJob                                                              .         PSWmiJob      True        Completed Test-Connection\n15 Invoke-Command -ComputerName . -ScriptBlock {Test-Connection .}                       localhost PSRemotingJob False       Completed Test-Connection .\n17 Invoke-Command -ComputerName ai8460p -ScriptBlock {Test-Connection .} -AsJob          ai8460p   PSRemotingJob False       Completed Test-Connection .\n19 Start-Job -ScriptBlock {Get-ChildItem C:\\}                                            localhost PSRemotingJob False       Completed Get-ChildItem C:\\\n21 Invoke-Command -ComputerName . -ScriptBlock {Get-ChildItem C:\\} -AsJob                localhost PSRemotingJob False       Completed Get-ChildItem C:\\\n23 Invoke-Command -ComputerName ai8460p   -ScriptBlock {Get-ChildItem C:\\} -AsJob        ai8460p   PSRemotingJob False       Completed Get-ChildItem C:\\\n\n\n07-17-13 19:47:35.29 C:\\Users\\ainbar\xc2\xbb\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

据我所知,无法在 PSWmiJob 上将 HasMoreData 设置为 False。Stop-Job不会执行此操作,重新启动 WinRM 也不会执行此操作,并且该属性是只读的。

\n