2015-06-03 18 views
10

Co próbuję zrobić, to uzyskać funkcję zatrzymania podawania potoku po osiągnięciu limitu czasu. Utworzyłem funkcję testową następująco:Zatrzymywanie potoku PowerShell, upewnij się, że koniec nazywa się

function Test-PipelineStuff 
{ 
    [cmdletbinding()] 
    Param(
     [Parameter(ValueFromPipeLIne=$true)][int]$Foo, 
     [Parameter(ValueFromPipeLIne=$true)][int]$MaxMins 
    ) 

    begin { 
     "THE START" 
     $StartTime = Get-Date 
     $StopTime = (get-date).AddMinutes($MaxMins) 
     "Stop time is: $StopTime" 
    } 

    process 
    { 
     $currTime = Get-Date 
     if($currTime -lt $StopTime){ 
      "Processing $Foo"    
     } 
     else{ 
      continue; 
     } 
    } 

    end { "THE END" } 
} 

Będzie to z pewnością zatrzymać rurociągu, ale nigdy nie wywołuje mój koniec „{}” blok, który w tym przypadku jest bardzo istotne. Czy ktoś wie dlaczego mój blok "end {}" nie jest wywoływany, gdy zatrzymuję potok używając "kontynuuj"? Zachowanie wydaje się być takie samo, jeśli rzucam wyjątek PipelineStoppedException.

+1

Przypuszczalnie 'kontynuuj' wyskakuje z pętli z zawartością, ale nie ma żadnej, więc przeskakuje całą twoją funkcję. To jednak nie jest zbyt pomocne. Nie jestem pewien, czy istnieje właściwy sposób robienia tego, co próbujesz zrobić tutaj. –

+1

Jak rozumiem, polecenia cmdlet, takie jak Select-Object -First 1, zwiększą wyjątek StopUpstreamCommandsException, aby zatrzymać potok, który jest wyjątkiem wewnętrznym i niewidoczny dla mojego własnego użytku. :( –

+0

Może umieścić swoje 'end {}' w innym bloku skryptowym, który możesz wywołać z klauzuli 'else {}' wewnątrz 'process {}'? –

Odpowiedz

2

Według about_Functions:

Po funkcja odbiera wszystkie obiekty w rurociągu, lista oświadczenie Koniec biegnie jeden raz. Jeśli nie użyto słów kluczowych Rozpocznij, Przetwórz lub Zakończ , wszystkie instrukcje będą traktowane jak lista wyciągów końcowych.

W ten sposób wystarczy pominąć blok else. Następnie wszystkie obiekty w potoku są przetwarzane, ale z powodu klauzuli if faktyczne przetwarzanie jest wykonywane tylko do momentu, w którym zostanie przekroczony limit czasowy.

+1

Jeśli muszę poczekać na przetworzenie wszystkich obiektów w rurociągu, to negatywnie wpływa to na próbę poinformowania go, aby zatrzymał się o określonej godzinie. Próbuję zatrzymać ten skrypt, jeśli przekroczy on limit czasowy i uniknąć przetwarzania wszystkich elementów poza tym limitem. Oczywiście mogę uzyskać blok końcowy do wykonania, jeśli przetwarzam wszystko, ale to nie jest mój cel. –

+0

Pytanie brzmiało, dlaczego blok końcowy nigdy nie zostanie wywołany. Odpowiedź brzmi, że wywoływana jest tylko wtedy, gdy przetwarzane są wszystkie elementy w potoku. –

+1

Nie, pytanie brzmiało, jak zatrzymać rurociąg i upewnić się, że koniec zostanie wywołany. –

0

Wyrzucenie wyjątku spowoduje niezmiennie wyjście z funkcji przedwcześnie (a także przerwanie/kontynuowanie dowolnej pętli zamykającej).

Można jednak umieścić funkcję oczyszczania w bloku begin który realizuje to, czego pierwotnie umieścić w bloku end i wywołać tę funkcję z zarówno Twój blok process - tuż przed continue - i blok end:

function Test-PipelineStuff 
{ 
    [cmdletbinding()] 
    Param(
     [Parameter(ValueFromPipeLine=$true)][int]$Foo, 
     [Parameter(ValueFromPipeLine=$true)][int]$MaxMins 
    ) 

    begin { 
     "THE START" 
     $StartTime = Get-Date 
     $StopTime = (get-date).AddMinutes($MaxMins) 
     "Stop time is: $StopTime" 

     # Embedded cleanup function. 
     function clean-up { 
      "THE END" 
     } 

    } 

    process 
    { 
     $currTime = Get-Date 
     if($currTime -lt $StopTime){ 
      "Processing $Foo"    
     } 
     else { 
      # Call the cleanup function just before stopping the pipeline. 
      clean-up 
      continue; 
     } 
    } 

    end { 
     # Normal termination: call the cleanup function. 
     clean-up 
    } 
} 
Powiązane problemy