Author Posts

June 22, 2015 at 11:47 am

EDIT and answer:
Turns out I was wrong believing that the error generated by ValidateScript would terminate the whole pipeline.

My tests on this behavior were incomplete and led me to believe that the result would be the same as a terminating error generated inside a PROCESS code block (which terminates the whole pipeline).

======

Let's say I write a function that gets a path via a parameter ($Path) and do something with it.

Usually, I'll use the handy "ValidateScript" parameter attribute to ensure that the path is valid.

But, if the function is written in a "pipelined" form (BEGIN, PROCESS, END) and can get the value of $Path via pipeline ("ValueFromPipelinebyPropertyName"), the entire pipeline will terminate at the first invalid $Path it encouters (because "ValidateScript" generates a terminating error).

What would be the best practice to validate values obtained in a pipeline without terminating the entire pipeline? So, If the pipeline receives an invalid path, it displays a (non terminating) error message and just moves on to the next object.

I managed to get this kind of behavior with a "try-catch" inside the PROCESS code block but it can get very complicated if the function can get more than 1 of its parameters via a pipeline.

Am I missing a better way to do this?

June 22, 2015 at 11:53 am

Sure, that's valid. But you control whether or not the validation script returns a terminating error. Maybe it should return a non-terminating error.

Keep in mind that whoever is RUNNING your command can add "-EA Stop" to force non-terminating errors to be trappable, terminating ones – if they want to. But the general pattern is, if you CAN keep going, you toss a non-term and keep going.

How are you currently producing your terminating error in the validation script?

June 22, 2015 at 12:42 pm

Thanks for the reply.

I did some additional testing and I was wrong assuming that the error generated by ValidateScript terminates the whole pipeline.

My tests on this behavior were incomplete and led me to believe that the result would be the same as a terminating error generated inside a PROCESS code block (which terminates the whole pipeline).

In fact, it behaves exactly like I first expected: the pipeline moves on to the next object if ValideScript throws an error:

function Test-PipelineError
{
[CmdletBinding()]
param(    
    [parameter(ValueFromPipeline=$true,ValueFromPipelinebyPropertyName=$True)]        
    [ValidateNotNullorEmpty()]    
    [ValidateScript({Test-Path $_})]
    [string]$Path
    )

BEGIN
{    
}

PROCESS
{
Write-Verbose "Doing something with $Path..."
}
       
END
{
}

}

$Paths = "C:\Windows","invalid path","C:\Users"

$Paths | Test-PipelineError -Verbose

The output would be something like: (exactly what's expected (and preferred)

VERBOSE: Doing something with C:\windows...
Test-PipelineError : Cannot validate argument on parameter 'Path'....
VERBOSE: Doing something with C:\Users...

So, assuming that errors generated by ValidateScript are terminating, they affect pipeline execution differently than a terminating error generated inside a PROCESS block.

Am I right?