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:
- Powershell: Creating and using custom attributes
- Powershell: Creating parameter validators and transforms
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."
}