Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stopping PowerShell pipeline, ensure end is called

What I'm trying to do is get a function to stop the pipeline feed when a time limit has been reached. I've created a test function as follows :

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

This will certainly stop the pipeline, but it never calls my "end{}" block, which, in this case is vital. Does anyone know why my "end{}" block isn't being called when I stop the pipeline using "continue"? Behaviour seems to be the same if I throw a PipelineStoppedException.

like image 811
campbell.rw Avatar asked Jun 03 '15 17:06

campbell.rw


2 Answers

According to about_Functions:

After the function receives all the objects in the pipeline, the End statement list runs one time. If no Begin, Process, or End keywords are used, all the statements are treated like an End statement list.

Thus you just need to omit the else block. Then all objects in the pipeline are processed, but due to the if clause the actual processing is only being done until the time limit is hit.

like image 187
Florian Feldhaus Avatar answered Oct 19 '22 11:10

Florian Feldhaus


Using break / continue or throwing an exception will invariably exit your function prematurely (and also break out of / continue any enclosing loop).

You can, however, embed a cleanup function in the begin block that implements what you originally put into your end block and call that function from both your process block - just before continue - and the 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
    }
}
like image 21
mklement0 Avatar answered Oct 19 '22 11:10

mklement0