2012-06-07 7 views
5

erstelle ich einen einfachen Hintergrund-Job in Powershell:"HasMoreData" gilt auch nach dem Receive-Job

Start-Job {"Hello"} 

prüfe ich mit Get-Job:

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

Als nächstes habe ich einfach die Ausgabe erhalten Get-Job, und läuft wieder

Receive-Job 1 
Get-Job 

ich kann sehen, dass „HasMoreData“ jetzt falsch ist, weil ich nicht dieangab 10 Parameter.

JEDOCH: es scheint, dass, wenn ich einen Job starte, nicht mit Start-Job oder Invoke-Command, dass dieser "HasMoreData" -Parameter nicht auf False geändert wird.

Beispiele:

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

Kann ich umgehen diese (falsche) Verhalten, so dass die Eigenschaft HasMoreData Schalter auf False, es sei denn, ich -keep angeben?

Danke!

Update: Es scheint für alle Anrufe mit dem -AsJob Parameter vorgenommen werden. Wenn Sie

Start-Job {Test-Connection .} 

führen Sie es funktioniert ("HasMoreData" falsch wird nach Receive-Job), aber

Test-Connection . -AsJob 

nicht.

Antwort

2

Kurze Antwort:

Es ist ein Fehler in PowerShell 2.0.

Es funktioniert gut für Blaine, weil er PowerShell 3 verwendet, würde ich Geld darauf legen.


Lange Antwort:

Die Start-Job Cmdlets und die -AsJob Schalter funktionieren anders.In der Dokumentation wird normalerweise erläutert, dass Start-Job Hintergrundaufträge lokal ausführen soll, während -AsJob Aufträge mit Befehlen starten soll, die auf Remotecomputern ausgeführt werden, das Auftragsobjekt jedoch lokal erstellt. Während das im Allgemeinen richtig ist, kann -AsJob auch verwendet werden, um Aufträge lokal auszuführen, und abhängig vom Befehl ist es manchmal nicht einmal in der Lage, den Befehl auf einem Remotecomputer auszuführen. Zum Beispiel läuft Get-WMIObject mit -AsJob und aufgerufen -ComputerName den Befehl auf dem angegebenen Remotecomputer, während Test-Connection aufgerufen mit -AsJob und -ComputerName führt den Befehl lokal und pingt den angegebenen Computer an.

Ich habe auch Dokumentation zu sehen, die erklären, dass Start-Job Arbeiten von lokalen IPC, während -AsJob eine Verbindung mit dem WinRM-Dienst des angegebenen Computers machen, auch wenn es die localhost ist, und dass PSRemoting muss auf dem lokalen und dem Zielcomputer aktiviert sein. Auch das ist nicht ganz so einfach. Ich habe festgestellt, dass ich kann Aufträge mit dem -AsJob auf dem lokalen Host mit WinRM und PSRemoting beide deaktiviert ausführen.

In jedem Fall startet PowerShell Jobs als eines von zwei JobTypes, PSWmiJob oder PSRemotingJob. Dies ist kontraintuitiv, weil Start-Job, die lokal Hintergrundjobs läuft, immer eine PSRemotingJob schafft, während -AsJob in der Regel eine PSWmiJob erzeugt, mit der Ausnahme, wenn es mit Invoke-Command, verwendet wird, die immer eine PSRemoting beginnt Job unabhängig davon, ob der Befehl auf einem Remotecomputer oder auf dem lokalen Host aufgerufen wird.

Sehen Sie sich das folgende Sitzungstranskript an, in dem ich Jobs auf unterschiedliche Weise erstellt habe. Ich habe mit drei Befehlen getestet: Get-WMIObject, die auf einem Remotecomputer ausgeführt wird, wenn mit -AsJob und aufgerufen wird ComputerName; Testverbindung, die immer lokal ausgeführt wird, wenn sie mit -AsJob aufgerufen wird (-ComputerName gibt an, welcher Computer anpingen soll, nicht wo der Befehl ausgeführt werden soll); und Get-ChildItem, das keinen -AsJob Parameter hat. Ich begann Jobs für jeden mit Start-Job, Invoke-Command -AsJob sowohl auf einen Remote-Computer und den lokalen Computer und die nativen -AsJob Schalter (für Befehle, die es haben).

Der Zweck der | %{$_.Name = '<the command preceding the pipe symbol>'} am Ende jedes Befehls besteht darin, jeden Job als den Befehl, der es erstellt hat, zu benennen, so dass es einfacher ist, in der Ausgabe zu sehen, welcher Job jedem Befehl entspricht. Es wirkt sich nicht auf die Ausführung der Jobs aus, sondern benennt jeden Job unmittelbar nach dem Erstellen in einen aussagekräftigeren Namen um.

Was Sie sehen, ist, dass, nachdem alle Arbeitsplätze erhalten werden (rcjb * 2>&1|Out-Null erhält sie alle auf einmal und unterdrückt die Ausgabe) wird die HasMoreData Eigenschaft PSRemotingJob Objekte auf False festgelegt, ob sie von Start-Job erstellt wurden, oder - AsJob, aber die HasMoreData-Eigenschaft von PSWmiJob-Objekten bleibt True. Abgesehen von den Beispielen, die ich hier reproduziert habe, habe ich festgestellt, dass dies konsequent gilt.

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» 

Fazit: Der Fehler ist in der PSWmiJob-Objekt. Unabhängig davon, wie der Job erstellt wurde und unabhängig davon, ob der Befehl lokal oder remote ausgeführt wird, wird die HasMoreData-Eigenschaft nach Receive-Job auf False gesetzt, wenn der JobType PSRemotingJob ist, bleibt aber True, wenn der JobType PSWmiJob ist.

Soweit ich das beurteilen kann, gibt es keine Möglichkeit, HasMoreData auf einem PSWmiJob auf False zu setzen. Stop-Job wird es nicht tun, Neustart WinRM wird es nicht tun, und die Eigenschaft ist schreibgeschützt.

+0

Ich hatte tatsächlich nach den früheren Antworten festgestellt, dass dies nur in Powershell V2 der Fall war. Danke Adi, nicht nur um zu bestätigen, sondern um sich die Zeit zu nehmen, so ausführlich und mit solcher Mühe zu erklären. – Joost

0

Dies funktioniert ordnungsgemäß. Ich habe mit der HasMoreData gearbeitet und es funktioniert so, wie Sie es wollen, in dem, wenn Sie eine Receive-Job machen, wird die HasMoreData auf false gesetzt. Es wird wahr bleiben, bis Sie Receive-Job.

+0

'HasMoreData' wird' False', wenn Sie 'Start-Job' verwenden, um den Job zu erstellen. Wenn Sie jedoch 'Test-Verbindung 'ausführen. -AsJob', dann 'Receive-Job',' HasMoreData' bleibt 'True'. Alles hängt davon ab, wie Sie den Job erstellt haben. Ich habe es gerade in Powershell 2 getestet (wird nächste Woche mit v3 versuchen). – Joost

+0

Dies basiert auf v3.0. Wenn ich es mit v3.0 ausführe, funktioniert es wie gesagt. Habe nicht in v2.0 geschaut. – BlackHatSamurai

1

Siehe diese Ausgabe:

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   . 

Sie sehen, dass die Job2 der Toplevel-Job ist, und es hat ein Kind Job mit dem Namen Job3 erstellt. Dort findet die eigentliche Handlung statt.

Können Sie den untergeordneten Job empfangen und überprüfen, ob HasMoreData noch festgelegt ist?