Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom error from parameters in PowerShell

Is it possible to have ValidateScript generate a custom error message when a test fails, like say Test-Path?

Instead of this:

Test-Folder : Cannot validate argument on parameter 'Folder'. The "Test-Path $_ -Path Type Container" validation script for the argument with value "blabla" did not return a result of True. Determine why the validation script failed, and then try the comma and again.

It would be nice to have it report this instead in the $Error variable:

The 'Folder' is not found, maybe there are network issues?

Code:

Function Test-Folder {
    Param (
        [parameter(Mandatory=$true)]
        [ValidateScript({Test-Path $_ -PathType Container})]
        [String]$Folder
    )
    Write-Host "The folder is: $Folder"
}

Workaround 1:

I could remove the Mandatory=$true and change it as below. But this doesn't give me the correct Get-Help syntax and doesn't do the Test-Path validation, because it only checks if the parameter is present.

Function Test-Folder {
    Param (
        [parameter()]
        [String]$Folder = $(throw "The $_ is not found, maybe there are network issues?")
    )
    Write-Host "The folder is: $Folder"
}

Workaround 2:

I found this workaround on a blog post, but the problem is that it generates two errors instead of one.

Function Test-Folder {
    Param (
        [parameter(Mandatory=$true)]
        [ValidateScript({
            if (Test-Path $_ -PathType Container) {$true}
            else {Throw "The $_ is not found, maybe there are network issues?"}})]
        [String]$Folder
    )
    Write-Host "The folder is: $Folder"
}

Workaround 3:

I could also try to make it more clear by adding a comment section. However, this is still not the desired result as the error needs to be readable to end users.

Function Test-Folder {
    Param (
        [parameter(Mandatory=$true)]
        [ValidateScript({
        # The folder is not found, maybe there are network issues?
        Test-Path $_ -PathType Container})]
        [String]$Folder
    )
    Write-Host "The folder is: $Folder"
}
like image 756
DarkLite1 Avatar asked Sep 29 '14 13:09

DarkLite1


People also ask

How do you write error messages in PowerShell?

To write a non-terminating error, enter an error message string, an ErrorRecord object, or an Exception object. Use the other parameters of Write-Error to populate the error record. Non-terminating errors write an error to the error stream, but they do not stop command processing.

What is ErrorAction in PowerShell?

ErrorAction parameter The -ErrorAction common parameter allows you to specify which action to take if a command fails. The available options are: Stop, Continue, SilentlyContinue, Ignore, or Inquire. If you're developing a Windows PowerShell workflow, you can also use the Suspend value.

How do I set parameters in PowerShell?

To create a parameter set, you must specify the ParameterSetName keyword of the Parameter attribute for every parameter in the parameter set. For parameters that belong to multiple parameter sets, add a Parameter attribute for each parameter set.

What is ErrorAction SilentlyContinue in PowerShell?

-ErrorAction:Ignore suppresses the error message and continues executing the command. Unlike SilentlyContinue, Ignore doesn't add the error message to the $Error automatic variable. The Ignore value is introduced in PowerShell 3.0.


1 Answers

Your ValidateScript should look something like this:

[ValidateScript({
    try {
        $Folder = Get-Item $_ -ErrorAction Stop
    } catch [System.Management.Automation.ItemNotFoundException] {
        Throw [System.Management.Automation.ItemNotFoundException] "${_} Maybe there are network issues?"
    }
    if ($Folder.PSIsContainer) {
        $True
    } else {
        Throw [System.Management.Automation.ValidationMetadataException] "The path '${_}' is not a container."
    }
})]

That will give you a message like this:

Test-Folder : Cannot validate argument on parameter 'Folder'. Cannot find path '\\server\Temp\asdf' because it does not exist. Maybe there are network issues?

Or:

Test-Folder : Cannot validate argument on parameter 'Folder'. The path '\\server\Temp\asdf' is not a container.

If the older versions of PowerShell are throwing a double error, you may need to test inside the function:

Function Test-Folder {
    Param (
        [parameter(Mandatory=$true)]
        [String]$Folder
    )

    try {
        $Folder = Get-Item $_ -ErrorAction Stop
    } catch [System.Management.Automation.ItemNotFoundException] {
        Throw [System.Management.Automation.ItemNotFoundException] "The '${Folder}' is not found, maybe there are network issues?"
    }

    if (-not $Folder.PSIsContainer) {
        Throw [System.Management.Automation.ApplicationFailedException] "The path '${_}' is not a container."
    }

    Write-Host "The folder is: ${Folder}"
}

The part that I always hated in PowerShell was trying to figure out what error to catch; without catching all. Since I finally figure it out, here's how:

PS > Resolve-Path 'asdf'
Resolve-Path : Cannot find path '.\asdf' because it does not exist.
At line:1 char:1
+ Resolve-Path 'asdf'
+ ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (asdf:String) [Resolve-Path], ItemNotFoundE
   xception
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.ResolvePathCommand

PS > $Error[0].Exception.GetType().FullName
System.Management.Automation.ItemNotFoundException
like image 137
VertigoRay Avatar answered Oct 19 '22 03:10

VertigoRay