locked
ValidateScript with polite error message RRS feed

  • Question

  • I've been scripting for a long time but am just starting to learn PowerShell.

    I'm passing a numeric value to PowerShell and want to validate that the input actually is numeric. Sounds like a job for ValidateScript.

    Here is my param. It produces the ugly exception message.

    param ( [ValidateScript({ if ($_ -match "^[0-9]*$") { $True } else { Throw "`nInvalid Input: The -MaxSize value must be numeric. '$_' is invalid" } })] $MaxSize=1000 ) "MaxSize = $MaxSize"

    PS C:\Users\Me\Downloads> .\PowerShell_Script.ps1 -ma 55555s
    C:\Users\Me\Downloads\PowerShell_Script.ps1 : Cannot validate argument on parameter 'MaxSize'.
    Invalid Input: The -MaxSize value must be numeric. '55555s' is invalid
    At line:1 char:39
    + .\@Download_PowerShell_Script.ps1 -ma 55555s
    +                                       ~~~~~~
        + CategoryInfo          : InvalidData: (:) [PowerShell_Script.ps1], ParameterBindingValidationException
        + FullyQualifiedErrorId : ParameterArgumentValidationError,PowerShell_Script.ps1

    I'd really prefer for the message to not be the full exception dump. Something friendlier like:

    MaxSize = 55555s
    
    Invalid Input: The -MaxSize value must be numeric. '' is invalid

    Is there any way to do this using ValidateScript? I can do if a remove ValidateScript and put the validation after the param in a simple if statement.

    Sunday, March 10, 2019 4:48 AM

Answers

  • This article explains ValidateScript

    https://powershell.org/2013/05/validatescript-for-beginners/

    If your priority is on user experience and you want to avoid a nasty red error all together they you will need to move the validation into the first part of the script (-Begin)

    You can still throw your own terminating error in the ValidateScript scriptblock that may suite your needs.  It will still be red, but will have your custom error messaging.

    karlprosser adds in the comment section of the article I posted an example of this.

    As the programmer I get some value from the additional information, but you really need to make this decision for yourself.

    • Edited by Ryan Shafer66 Monday, March 11, 2019 12:00 AM
    • Marked as answer by Bri7668 Monday, March 11, 2019 11:41 PM
    Sunday, March 10, 2019 10:43 PM

All replies

  • Return true/false and don't throe an exception.

    \_(ツ)_/

    Sunday, March 10, 2019 6:11 AM
  • function test{
        param(
        [ValidateScript({$_ -match '^[0-9]*$'})]
        $MaxSize = 1000
        )
        "Maxsize = $MaxSize"
    }

    Validation should only ever return true/false.  It should not perform other than a parameter check.  A false return will throw the correct exception.


    \_(ツ)_/


    Sunday, March 10, 2019 6:15 AM
  • This article explains ValidateScript

    https://powershell.org/2013/05/validatescript-for-beginners/

    If your priority is on user experience and you want to avoid a nasty red error all together they you will need to move the validation into the first part of the script (-Begin)

    You can still throw your own terminating error in the ValidateScript scriptblock that may suite your needs.  It will still be red, but will have your custom error messaging.

    karlprosser adds in the comment section of the article I posted an example of this.

    As the programmer I get some value from the additional information, but you really need to make this decision for yourself.

    • Edited by Ryan Shafer66 Monday, March 11, 2019 12:00 AM
    • Marked as answer by Bri7668 Monday, March 11, 2019 11:41 PM
    Sunday, March 10, 2019 10:43 PM
  • If I wanted the user to see the exception, then this would be fine. However, my desire is for the user to see a nice polite message like:

    >PowerShell_Script.ps1 -m asdf
    MaxSize       = asdf
    
    Invalid Input: The -MaxSize value must be numeric. 'asdf' is invalid

    Seeing the full exception message would cause them to mess up their pants. ;)

    Monday, March 11, 2019 11:34 PM
  • That is what you get when the validation script is done correctly:

    PS D:\scripts> function test{
    >>     param(
    >>     [ValidateScript({$_ -match '^[0-9]*$'})]
    >>     $MaxSize = 1000
    >>     )
    >>     "Maxsize = $MaxSize"
    >> }
    PS D:\scripts> test m
    test : Cannot validate argument on parameter 'MaxSize'. The "$_ -match '^[0-9]*$'" validation script for the argument with value "m" did not return
    a result of True. Determine why the validation script failed, and then try the command again.
    At line:1 char:6
    + test m
    +      ~
        + CategoryInfo          : InvalidData: (:) [test], ParameterBindingValidationException
        + FullyQualifiedErrorId : ParameterArgumentValidationError,test
    
    PS D:\scripts>


    \_(ツ)_/

    Monday, March 11, 2019 11:38 PM
  • Thank you, Ryan, for pointing me there. Maybe not the answer I was hoping for, but a great answer anyway.
    Monday, March 11, 2019 11:42 PM
  • I feel like you have probably moved on from this already, but if you want an item to be of a specific type, there is a much easier - and better way to go about it: specify the object type in the param block. For instance, consider the following function:

    function Invoke-Test {
        param (
            [int] $MaxSize
        )
        $MaxSize.getType()
    }

    Because $MaxSize is declared to be an [int], Powershell will automatically try to convert whatever value it is passed into an [int] at runtime. If the conversion fails, an error is thrown. So:

    Invoke-Test -MaxSize "10"

    "10" is passed as a [string], yet the function returns:

    IsPublic IsSerial Name                                     BaseType                                                         
    -------- -------- ----                                     --------                                                         
    True     True     Int32                                    System.ValueType  

    and 

    Invoke-Test -MaxSize 10a

    "10a" cannot be converted to an [int], so an error is thrown:

    Invoke-Test : Cannot process argument transformation on parameter 'MaxSize'. Cannot convert value "10a" to type 
    "System.Int32". Error: "Input string was not in a correct format."
    At line:1 char:22
    + Invoke-Test -MaxSize 10a
    +                      ~~~
        + CategoryInfo          : InvalidData: (:) [Invoke-Test], ParameterBindingArgumentTransformationException
        + FullyQualifiedErrorId : ParameterArgumentTransformationError,Invoke-Test

    Sunday, October 6, 2019 6:30 PM