5

I'd like to call a PowerShell script this way :
script.ps1 -path mypath\to\files\ -days 6 -hours 0

To validate the command line arguments, I can either do it by hand, either rely on the param syntax :

Param (
    [Parameter(Mandatory=$true )] [string] $path,
    [Parameter(Mandatory=$false)] [int]    $days,
    [Parameter(Mandatory=$false)] [int]    $hours
)

 

 

If I use the param syntax :

  • the param definition must be the first line in the script (excluding comments). Okay, not a problem for me

  • in case of incorrect parameters, I can't catch the error (for example to display a custom error message)

     

I'd like to display a custom error message when the script is called with wrong parameters.
Is it possible, and how, to catch the exception in case of parameter error ?

5 Answers 5

3

So okay, it is not possible to use param AND to catch the related exceptions.

Sign up to request clarification or add additional context in comments.

2 Comments

It still seems to be possible, see my answer.
My vote was +1 because I understood the question in a different way and in this way it was interesting. Perhaps I should have abstained, the question is not clear. You may try to edit it and explain the problem better. I'll try to help again.
1

The examples are for functions (simple and advanced) but the same idea should work for scripts with param as well:

# Simple function.
# Everything not declared in `param` goes to $args.
# If $args is not empty then there are "invalid" parameters or "unexpected" arguments
function test {
    param (
        [string]$path,
        [int]$days,
        [int]$hours
    )
    # check $args and throw an error (in here we just write a warning)
    if ($args) { Write-Warning "Unknown arguments: $args" }
}

Or

# Advanced function.
# For an advanced function we can use an extra argument $args
# with an attribute `[Parameter(ValueFromRemainingArguments=$true)]`
function test {
    param (
        [Parameter(Mandatory=$true )] [string] $path,
        [Parameter(Mandatory=$false)] [int]    $days,
        [Parameter(Mandatory=$false)] [int]    $hours,
        [Parameter(ValueFromRemainingArguments=$true)] $args
    )
    # check $args and throw an error (in this test we just write a warning)
    if ($args) { Write-Warning "Unknown arguments: $args" }
}

The following test:

# invalid parameter
test -path p -invalid -days 5

# too many arguments
test -path p 5 5 extra

in both cases produces the same output:

WARNING: Unknown arguments: -invalid
WARNING: Unknown arguments: extra

1 Comment

This don't address the question : how to catch the exception in case of parameter error ? If you have an error on the mandatory paramaters, the script just crash and you can do nothing against it.
1

A possible workaround is to wrap your actual function in another one. Something similar to a private/public relation. Example:

function Example-Private
{
    [CmdletBinding()]
    Param
    (
        [ValidateNotNullOrEmpty()]
        [string]$Arg1,
        [ValidateNotNullOrEmpty()]
        [string]$Arg2   
   )

   # Do what you need
}

function Example-Public
{
    [CmdletBinding()]
    Param
    (
        [string]$Arg1,
        [string]$Arg2   
    )

    try
    {
       Example-Private $Arg1 $Arg2
    }
    catch
    {
       # Display a user-friendly message, save exception into a log file, etc.
    }
}

If you are working on a module you could take a look here how to export your public functions and hide the private ones: Export Powershell Functions

1 Comment

This is the only thing that worked for me. Powershell v5
-1

In the Begin block you can always do further validation on the parameters but if the parameter is wrong, I think you wouldn't want to continue execution. That is, you'd want to throw a terminating error. Here's an example:

param (
    [Parameter(Mandatory=$true )] [string] $path,
    [Parameter(Mandatory=$false)] [int]    $days,
    [Parameter(Mandatory=$false)] [int]    $hours
)

Begin {
    if ($hours -lt 0 -or $hours -gt 23) {
        throw "Hours parameter must be between 0 and 23"
    }
}

That said, I'm not sure that's any better than using PowerShell's built-in parameter validation functionality e.g.:

param (
    [Parameter(Mandatory=$true )] [string] $path,
    [Parameter(Mandatory=$false)] [int]    $days,
    [Parameter(Mandatory=$false)]
    [ValidateRange(0,23)]
    [int]
    $hours
)

5 Comments

This don't work. It don't allow the code to catch any exception during the 'param' validation, for exemple if I add an extra parameter.
Which this doesn't work? The first example, which is doing manual validation or the second example which uses parameter validation. I suspect you mean the latter didn't work. Did you try the approach in the first example - validating in the Begin block?
I tested the first example. I run with script.ps1 -path xxx -dummy yyy and an exception is fired without executing 'begin'.
-Dummy is not a declared parameter. If you want to handled invalid parameters then don't use [Parameter(...)].
This is the question. If you know this is not possible, why give a wrong answer ?
-1

you can do that with the param syntax, if you add a string-type dummy-parameter with the property "ValueFromRemainingArguments". Then you can check this dummy-parameter in your script and take appropriate actions, e.g.:

Param(
    [Parameter(Mandatory=$false)]
    [SWITCH]$myparam1,

    [Parameter(Mandatory=$false)]
    [SWITCH]$myparam2,

    [parameter(Mandatory=$false,ValueFromRemainingArguments=$true)]
    [STRING]$dummy     
    )

if ($dummy -eq anythingYouDontLike) throwAMessageOrSomething.

1 Comment

As far as I understand this doesn't address the question, which is how to avoid the script crashing if one of the param validation fails, which happens before even reaching your "ValueFromRemainingArguments"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.