我在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”现在为false,因为我没有指定-keep
参数。
但是:似乎无论何时我开始工作,而不是Start-Job
或Invoke-Command
,这个“HasMoreData”参数都不会更改为False。
示例:
Get-WMIObject win32_bios -AsJob
Test-Connection . -AsJob
我是否可以绕过此(错误)行为,以便属性HasMoreData切换为False,除非我指定-keep
?
谢谢!
更新:它似乎适用于使用-AsJob
参数进行的所有调用。如果你运行
Start-Job {Test-Connection .}
它有效(Receive-Job
后“HasMoreData”变为False),但
Test-Connection . -AsJob
没有。
答案 0 :(得分:2)
简短回答:
这是PowerShell 2.0中的一个错误。
Blaine工作正常,因为他正在使用PowerShell 3,我会把钱投入其中。
答案很长:
Start-Job cmdlet和 -AsJob 开关的工作方式不同。文档通常解释 Start-Job 旨在在本地运行后台作业,而 -AsJob 旨在使用在远程计算机上运行但在本地创建作业对象的命令启动作业。虽然这通常是正确的,但 -AsJob 也可用于在本地运行作业,并且根据命令,它有时甚至无法在远程计算机上运行该命令。例如,使用 -AsJob 调用的 Get-WMIObject 和 -ComputerName 在指定的远程计算机上运行命令,而测试连接使用 -AsJob 和 -Computername 调用在本地运行命令并ping指定的计算机。
我还看过文档说明 Start-Job 由本地IPC工作,而 -AsJob 与指定计算机的WinRM服务建立连接,甚至如果是本地主机,则必须在本地和目标计算机上启用PSRemoting。再说一次,这并不是那么简单。我发现我可以在本地主机上使用 -AsJob 开关运行作业,同时WinRM和PSRemoting都被禁用。
在任何情况下,PowerShell都会将作业作为两个JobTypes,PSWmiJob或PSRemotingJob之一启动。这是违反直觉的,因为在本地运行后台作业的 Start-Job 总是会创建一个PSRemotingJob,而 -AsJob 通常会创建一个PSWmiJob,除非它与< strong> Invoke-Command ,无论是在远程计算机上还是在本地主机上调用该命令,它总是启动PSRemoting作业。
查看以下会话记录,其中我以不同的方式创建了作业。我测试了三个命令: Get-WMIObject ,当使用 -AsJob 和 ComputerName 调用时,它在远程计算机上运行; 测试连接,在使用 -AsJob 调用时始终在本地运行( -ComputerName 指定要ping的计算机,而不是运行命令的位置) ;和 Get-ChildItem ,它没有 -AsJob 参数。我在远程计算机和本地计算机上使用 Start-Job , Invoke-Command -AsJob 以及本机 -AsJob switch(对于拥有它的命令)。
每个命令末尾的| %{$_.Name = '<the command preceding the pipe symbol>'}
的目的是将每个作业命名为创建它的命令,因此在输出中更容易看到哪个作业对应于每个命令。它对作业的操作没有影响,它只是在创建后立即将每个作业重命名为更有意义的名称。
你会看到,在收到所有作业后(rcjb * 2>&1|Out-Null
一次接收所有作业并禁止输出),PSRemotingJob对象的HasMoreData属性设置为False,无论它们是由创建的Start-Job 或 -AsJob ,但PSWmiJob对象的HasMoreData属性仍为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对象中。无论创建作业的方式如何,无论命令是本地还是远程运行,在 Receive-Job 之后,如果JobType为PSRemotingJob,则HasMoreData属性设置为False,但如果JobType是PSWmiJob。
据我所知,没有办法在PSWmiJob上将HasMoreData设置为False。 停止作业不会这样做,重新启动WinRM将不会这样做,并且该属性是只读的。
答案 1 :(得分: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是否仍然设置?
答案 2 :(得分:0)
这确实有效。我一直在使用HasMoreData
,它按您希望的方式工作,因为如果您执行Receive-Job
,则HasMoreData
设置为false。它会保持真实,直到你Receive-Job
。
答案 3 :(得分:0)
我在3台计算机上对PS3.0,PS4.0,PS5.1和PS6.1的称呼相同! 我的测试创建了一个没有输出的工作
Start-Job -name "RDS-Job_JobName" -ScriptBlock {1..99 |%{Start-Sleep -m 1000} | out-null}
get-job -HasMoreData:$true | Receive-Job
get-job -HasMoreData:$true
我不明白! HasMoreData始终为 True
Id Name PSJobTypeName State HasMoreData Location
-- ---- ------------- ----- ----------- --------
1 RDS-Job_JobName BackgroundJob Running True localhost