Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

PowerShell Scripting with [ValidateSet]

Posted on April 16, 2012July 16, 2013

Today we'll continue our exploration of the parameter validation attributes you can use in you PowerShell scripting. We've already looked at [ValidateRange] and [ValidateScript]. Another attribute you are likely to use is [ValidateSet()]. You can use this to verify that the parameter value belongs to a pre-defined set.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!

To use, specify a comma separated list of possible values.

[ValidateSet("Apple","Banana","Cherry")]
[string]$Fruit

If the person running the script specifies something other than "Apple", "Banana", or "Cherry" as a value for -Fruit, PowerShell will throw an exception and the script will fail to run. And in case you were wondering, this is not case-sensitive.

If you are going to use this attribute, I recommend providing documentation either in comment based help and/or as part of a help message so the user knows what values to expect. The PowerShell help system doesn't automatically detect this attribute and use it in syntax display as you might have seen with other cmdlets.

Here's a more practical example.

#requires -version 2.0

Param (
[Parameter(Position=0)]
[ValidateSet("System","Application","Security","Directory Service","DNS Server")]
[string]$Log="System",
[ValidateRange(10,1000)]
[int]$Count=100,
[Parameter(Position=1,Mandatory=$True,
HelpMessage="What type of export file do you want to create? Valid choices are CSV, XML, CLIXML.")]
[ValidateSet("csv","xml","clixml")]
[string]$Export,
[ValidateNotNullorEmpty()]
[string]$Path="C:\Work",
[string]$Computername=$env:Computername
)

Write-Verbose "Getting last $Count events from $log event log on $computername"
#base logname
$base="{0:yyyyMMdd}_{1}_{2}" -f (Get-date),$Computername,$Log

Try {
    $data=Get-EventLog -LogName $log -ComputerName $Computername -Newest $Count -errorAction Stop
}
Catch {
    Write-Warning "Failed to retrieve $log event log entries from $computername. $($_.Exception.Message)"
}

If ($data) {
    Write-Verbose "Exporting results to $($export.ToUpper())"
    Switch ($Export) {
        "csv" { $File=Join-path -Path $Path -ChildPath "$base.csv"
                $data | Export-Csv -Path $File  
              }
        "xml" {  $File=Join-path -Path $Path -ChildPath "$base.xml"
                ($data | ConvertTo-XML).Save($File)
               }
        "clixml" {$File= Join-path -Path $Path -ChildPath "$base.xml"
                $data | Export-Clixml -Path $File
                }
    } #switch

   Write-Verbose "Results exported to $File"

} #if $data

The script will get recent events from a specified log on a specified computer and export the results. My script will only export from a short list of logs which I'm validating.

[ValidateSet("System","Application","Security","Directory Service","DNS Server")]
[string]$Log="System",

If an invalid value is detected PowerShell will complain.

PS S:\> .\Demo-ValidateSet.ps1 -comp jdhit-dc01 -log dns -verbose -Export clixml

C:\scripts\Demo-ValidateSet.ps1 : Cannot validate argument on parameter 'Log'.
The argument "dns" does not belong to the set "System,Application,Security,Dire
ctory Service,DNS Server" specified by the ValidateSet attribute. Supply an arg
ument that is in the set and then try the command again.
At line:1 char:45
+ .\Demo-ValidateSet.ps1 -comp jdhit-dc01 -log <<<<  dns -verbose -Export clixm
l
    + CategoryInfo          : InvalidData: (:) [Demo-ValidateSet.ps1], Paramet
   erBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Demo-ValidateSe
   t.ps1

The error message displays the expected values, but the better approach might be to include them in a help message, especially if the parameter is mandatory. For example, this script will export results based on -Export.

[Parameter(Position=1,Mandatory=$True,
HelpMessage="What type of export file do you want to create? Valid choices are CSV, XML, CLIXML.")]
[ValidateSet("csv","xml","clixml")]
[string]$Export,

If you'd like to try out my demo script, you can download Demo-ValidateSet.


Behind the PowerShell Pipeline

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

11 thoughts on “PowerShell Scripting with [ValidateSet]”

  1. walid toumi says:
    April 16, 2012 at 3:22 pm

    hi

    you can use ignorecase keyword:


    PS> gc function:\test-foo

    function test-foo {
    param(
    [Parameter(Position=0)]
    [validateset('foo','bar',ignorecase=$false)]
    $test)

    $test

    }


    PS> test-foo foo
    foo

    PS> test-foo FOO
    error

    1. Jeffery Hicks says:
      April 16, 2012 at 3:38 pm

      That is a very handy tip. Thanks for sharing.

  2. Shay Levy says:
    April 17, 2012 at 2:49 am

    One of the benfits of using ValidateSet (or Enum types) in PowerShell 3.0 is that you get tab expansion on the ValidateSet/Enum values.

  3. JV says:
    April 17, 2012 at 11:33 am

    Jeff
    Nice work on validation. Haveyouthough of rollimg it up into a help file. (about_jh_advanced_validation) or similar.

    1. Jeffery Hicks says:
      April 17, 2012 at 11:49 am

      Thanks for the positive feedback. I’ll have to think about the best way to bundle everything. I still have one or two more topics to cover.

  4. Pingback: Parameter validation « Mario's Blog
  5. brendan62269 says:
    August 2, 2012 at 6:05 pm

    Hey Jeff;
    Great article! Maybe you can point me in the right direction…. or maybe I just need to stop looking for ways to be lazy 🙂

    I would like to ValidateSet against a scriptblock (similar to a ValidateScript). For example:

    function find-processid {
    [CmdletBinding()]
    param(
    [ValidateSet({(Get-Process).Name})]
    $ProcessName
    )
    $Result = (Get-Process -Name $ProcessName)
    $Result.id
    }

    This always bombs because it is reading the scriptblock literally. I know that I can make this work by changing ValidateSet to ValidateScript, the real aim here is to get tab completion to cycle through my choices in a dymanic situation (laziness).

    Do you think there a way to make ValidateSet read the scriptblock when the function is called (some funky $([]::{}.()) magic that only you and maybe one other person has ever seen) or should I be looking to use a RuntimeDefinedParameter instead?

    1. Jeffery Hicks says:
      August 2, 2012 at 6:18 pm

      ValidateSet really seems to need to be constant and predefined. But I think you can get the same results with ValidateScript.

      param (
      [Parameter(Position=0,Mandatory=$True)]
      [ValidateScript({$(get-process | Select -expand name) -contains $_})]
      [string]$name
      )

  6. brendan62269 says:
    August 3, 2012 at 12:57 pm

    When you do that does tab completion on the -name paramter work for you? Maybe something’s wrong with my shell…

    Function Get-ProcessID{
    param (
    [Parameter(Position=0,Mandatory=$True)]
    [ValidateScript({$(get-process | Select -expand name) -contains $_})]
    [string]$name
    )
    $prc = Get-Process -Name $_
    $prc.id
    }

    get-processid -name

    Returns files in the local directory in my shell, or am I doing something else wrong?

    1. Jeffery Hicks says:
      August 3, 2012 at 1:30 pm

      No that won’t work. What you want will work in PowerShell v3. You could type Get-Process -name press space and then tab and it would cycle through the all the current processes. You are misunderstanding what a function does. I think you should step back and regroup. Feel free to use the forum at http://bit.ly/AskJeffHicks

  7. brendan62269 says:
    August 3, 2012 at 11:43 pm

    I think the example was just too simple. Thanks for your time Jeff, I’ll figure it out.

Comments are closed.

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d