Home > Net >  Unable to utilize ErrorMessage property with ValidateSet in Function
Unable to utilize ErrorMessage property with ValidateSet in Function

Time:05-04

I am currently practicing the use of functions in PowerShell and seem to be running into an error. I created the function below to accept DC Super Hero names and return the name of the hero being passed to the function. The function I have created can be seen below:

function Get-DCHero {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)][ValidateSet('Batman','Superman','Aquaman','Wonder Woman','Flash',ErrorMessage = "'{0}' is not a DC Super Hero. Please trying one of the following: '{1}'")]
        [string]$Name
    )

    Write-OutPut "$Name is a DC Super hero."
}

As of now the function works properly without the ErrorMessage portion on the ValidateSet. When including the ErrorMessage portion I am receiving the following error:

Get-DCHero -Name

Property 'ErrorMessage' cannot be found for type 'System.Management.Automation.CmdletBindingAttribute'.  
At C:\Users\AAP8801\DCSuperHero.ps1:5 char:98
  ... n','Flash', ErrorMessage = "'{0}' is not a DC Super Hero. Please tryi ...
                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      CategoryInfo          : InvalidOperation: (ErrorMessage = ...llowing: '{1}'":NamedAttributeArgume  
   ntAst) [], RuntimeException
      FullyQualifiedErrorId : PropertyNotFoundForType

When a parameter is passed to the function that is not part of the validation set I would like to able to edit the error message being throw. Can anyone tell me why I am unable to do this successfully?

CodePudding user response:

As Mathias explained in comments, the ErrorMessage property is available starting from PowerShell SDK version 6.2.0.

As a workaround on Windows PowerShell, you could use the ValidateScript Attribute Declaration or you could create your own Attribute Declaration inheriting from the ValidateSet Base Type, ValidateEnumeratedArgumentsAttribute.

The following example can help you get started, and if you're interested in learning more, I would recommend you these nice articles from Kevin Marquette:

using namespace System.Management.Automation

class MyDCHeroSet : ValidateEnumeratedArgumentsAttribute {
    hidden [string[]] $Set = 'Batman','Superman','Aquaman','Wonder Woman','Flash'

    [void] ValidateElement ([object] $Object) {
        if($Object -notin $this.Set) {
            throw "$Object is not in set!!"
        }
    }

}

function Get-DCHero {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [MyDCHeroSet()]
        [string] $Name
    )

    Write-OutPut "$Name is a DC Super hero."
}

Get-DCHero -Name SpiderMan

CodePudding user response:

To complement Santiago Squarzon's helpful answer by spelling out the [ValidateScript()] workaround he mentions, which is slightly easier than defining a custom attribute class:

function Get-DCHero {
  [CmdletBinding()]
  param (
      [Parameter(Mandatory)]
      [ValidateScript({
        $set = 'Batman','Superman','Aquaman','Wonder Woman','Flash'
        if ($_ -in $set) { return $true } # OK
        throw "'$_' is not a DC superhero. Please try one of the following: '$($set -join ',')'"
      })]
      [string]$Name
  )

  "$Name is a DC superhero."
}
  • Related