views:

65

answers:

1

Hi all

I am using New-Object System.Management.Automation.PipelineStoppedException To stop the pipeline OK..works..

But how Can I test in the next cmdlet if was stopped ?

Foo1 | foo2 | foo3

Stop in foo1, but goes to foo2. I want to test if was stopped in foo1 to stop too in each function

function foo1 {
    process {
        try {
            #do
        } catch {
            New-Object System.Management.Automation.PipelineStoppedException
        }
    }
}

and still going to the next cmdlet, as stopped by error I want to stop in each next cmdlets..:)

Thanks !!!

A: 

You've misunderstood how pipelines work. When a sequence of objects is sent to a pipeline, each individual object is passed through the entire pipeline before the next object is processed. Consider the following functions:

function First() {
    process {
        Write-Host "First: $_";
        $_
    }
}

function Second() {
    process {
        Write-Host "Second: $_";
    }
}

The first function outputs "First" and the value of the pipeline object, and then passes the object on. The second merely outputs "Second" and the pipeline object. Now, when you push an array to a pipeline composed of these two functions, what do you expect to see?

The actual result is this:

PS C:\Users\Lauri> ,1,2,3 | first | second
First: 1
Second: 1
First: 2
Second: 2
First: 3
Second: 3

Now, with this information handy, we can deduce that when a function or cmdlet in the pipeline throws an exception to stop processing, the entire pipeline stops. But we can easily verify it too. Let's modify First as follows:

function First() {
    process {
        throw New-Object System.Management.Automation.PipelineStoppedException
    }
}

and then try the same pipeline again:

PS C:\Users\Lauri> ,1,2,3 | first | second

The result is empty, because the moment the first object is passed to "First", it throws an exception, and the entire pipeline is aborted.

In summary, you can't test if the processing was aborted further down the pipeline, because the execution will never get there.

[Edit] One more interesting tidbit: the Begin blocks of all functions are run first, and the End blocks are all run last, so if you throw an exception in the Process block higher up in the pipeline, the Begin block of all the pipeline functions will already have run:

function First() {
    begin {
        Write-Host "First begin"
    }
    process {
        throw New-Object System.Management.Automation.PipelineStoppedException
    }
    end {
        Write-Host "First end"
    }
}

function Second() {
    begin {
        Write-Host "Second begin"
    }
    process {
        Write-Host "Second: $_"
    }
    end {
        Write-Host "Second end"
    }
}

PS C:\Users\Lauri> ,1,2,3 | first | second
First begin
Second begin

[Edit 2]

Another potentially interesting consequence is that if an exception occurs and you want the pipeline to continue after that, you'll need to return something in the catch block that catches it:

function CauseException {
    throw New-Object Exception
}

function First() {
    process {
        try {
            CauseException
        } catch {
            "Error"
        }
    }
}

function Second() {
    process {
        Write-Host "Second: $_"
    }
}

PS C:\Users\Lauri> ,1,2,3 | first | second
Second: Error
Second: Error
Second: Error
Rytmis
I think I understand. I'll do some testing and post. Thank you very much
can you help with this example ?.. If catch in any function, does not execute in thhe nexts.. foo1 | foo2 | foo3 foo1 { process { try { dosomething } catch { } } } foo2 { process { try { dosomething } catch { } } } foo3 { process { try { dosomething } catch { } } }
If you want the pipeline to continue after you catch an exception in a pipeline function, you need to *return* something from the catch block.
Rytmis
Rytmis, thanks for your help, actually I expressed myself badly, I want when I have a excpetion in catch , it stops the pipeline and do not continue in the next cmdltes
In that case, what you want to do is throw a PipelineStoppedException in the catch block.
Rytmis
PERFECT My friend :) You save my day. Many Many Thanks
... which is what you're doing in your example. The point of my long post was to help you understand that if you do so, it will halt the execution. :-)
Rytmis
yes, very cool you explain "How" the things happens ...:) I am not puting "throw", so I belive because this do not stop running in the other fucntions. Aganin Thanks
On further inspection, throwing that exception doesn't seem to be the official way to do it, though -- in fact, documentation suggests that it's a consequence of the stopped pipeline. I'm going to do some further digging to see if I can find a better way.
Rytmis
Yes, actually I saw this tip in the post to Dr Tobias, and after Jeffrey Snover saying that. If you have another solution, please I appreciate
Well, it looks like the `break` statement works in a similar fashion.
Rytmis
Damn, I was too hasty. It doesn't behave in exactly the same way. Sorry for the back-and-forth, I'm sort of learning this as we go here. :-)
Rytmis
NP man..you already helped me :)

related questions