Остановить конвейер PowerShell, обеспечить, чтобы конец был вызван

То, что я пытаюсь сделать, это получить функцию, чтобы остановить фид конвейера, когда достигнут лимит времени. Я создал тестовую функцию следующим образом:

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

Это, безусловно, остановит конвейер, но никогда не называет мой блок "end {}", что в этом случае жизненно важно. Кто-нибудь знает, почему мой "end {}" блок не вызывается, когда я останавливаю конвейер, используя "continue"? Поведение, похоже, одинаково, если я выкидываю исключение PipelineStoppedException.

Ответ 1

Согласно about_Functions:

После того, как функция получит все объекты в конвейере, End Список операторов запускается один раз. Если нет начальных, технологических или конечных ключевых слов, все операторы рассматриваются как список команд End.

Таким образом, вам просто нужно опустить блок else. Затем обрабатываются все объекты в конвейере, но из-за предложения if фактическая обработка выполняется только до тех пор, пока не будет достигнут срок.

Ответ 2

Использование break/continue или выброс исключений всегда будет преждевременно выходить из вашей функции (а также вырваться из/продолжить любой замкнутый цикл).

Однако вы можете внедрить функцию очистки в блок begin, который реализует то, что вы изначально вложили в ваш блок end, и вызовите эту функцию из вашего блока process - перед continue - и end block:

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