2015-06-03 7 views
10

Quello che sto cercando di fare è ottenere una funzione per fermare l'avanzamento gasdotto quando è stato raggiunto un limite di tempo. Ho creato una funzione di test come segue:Fermare PowerShell gasdotto, garantire fine si chiama

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" } 
} 

Questo sarà certamente fermare la pipeline, ma non è mai chiama il mio "end {}" blocco, che, in questo caso, è di vitale importanza. Qualcuno sa perché il mio blocco "end {}" non viene chiamato quando interrompo la pipeline usando "continue"? Il comportamento sembra essere lo stesso se lancio una PipelineStoppedException.

+1

Presumibilmente 'CONTINUE sta saltando fuori del suo ciclo che contiene solo non ce n'è uno in modo che salta chiaro della vostra intera funzione. Questo non è esattamente utile però. Non sono sicuro se c'è un modo corretto di fare ciò che stai cercando di fare qui. –

+1

A quanto ho capito, i cmdlet come Select-Object -First 1 generano StopUpstreamCommandsException per interrompere la pipeline, che è un'eccezione interna e non visibile per uso personale. :( –

+0

Forse metti l'elaborazione 'end {}' in un diverso scriptblock che puoi chiamare dalla clausola 'else {}' all'interno di 'process {}'? –

risposta

2

Secondo about_Functions:

Dopo la funzione riceve tutti gli oggetti in cantiere, la lista istruzione End viene eseguito una volta. Se non vengono utilizzate le parole chiave Inizio, Processo o Fine , tutte le istruzioni vengono trattate come un elenco di istruzioni Fine.

Quindi è sufficiente omettere il blocco else. Quindi tutti gli oggetti nella pipeline vengono elaborati, ma a causa della clausola if, l'elaborazione effettiva viene eseguita solo fino al raggiungimento del limite di tempo.

+1

Se devo aspettare che elabori tutti gli oggetti nella pipeline, praticamente nega il beneficio di provare a dirgli di fermarsi a una certa ora. Sto cercando di arrestare questo script se raggiunge il limite di tempo ed evita di elaborare tutti gli elementi al di fuori di tale limite. Naturalmente posso eseguire il blocco finale se elaboro tutto, ma non è questo il mio obiettivo. –

+0

La domanda era: perché il blocco finale non viene mai chiamato. La risposta è che viene chiamato solo se tutti gli elementi nella pipeline vengono elaborati. –

+1

No, la domanda era: come posso fermare la pipeline e assicurarmi che venga chiamata la fine. –

0

L'utilizzo di break/continue o il lancio di un'eccezione invariabilmente interrompono la funzione prematuramente (e interrompono anche/continuano qualsiasi ciclo di chiusura).

È possibile, tuttavia, incorporare una funzione di pulizia nel blocco begin che implementa quello che originariamente mettete nel vostro end blocco e chiamare quella funzione da sia tuo process blocca - poco prima continue-e il blocco 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 
    } 
}