Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to implement IValidateSetValuesGenerator for script parameter validation?

Tags:

powershell

In the example in the powershell documentation you need to implement a class, like: Class SoundNames : System.Management.Automation.IValidateSetValuesGenerator { ... }

But, how can you do this in a script based cmdlet? (See "Parameters in scripts" in about_Scripts).

In a script cmdlet the first line must be param( ... ). Unless "SoundNames" is already defined, then it fails with Unable to find type [SoundNames]

If this type is already defined in the powershell session, this works ... but I'd like a stand-alone script that doesn't require the user do something first to define this type (e.g. dot-sourcing some other file).

I want to define a parameter that accepts only *.txt filenames (for existing files in a specific directory).

like image 212
joeking Avatar asked Nov 19 '25 17:11

joeking


1 Answers

You can't do this in a (stand-alone) script, for the reason you state yourself:

  • The param block (possibly preceded by a [CmdletBinding()] attribute, must be at the very start of the file (leaving using statements aside).

  • This precludes defining a custom class that implements the IValidateSetValuesGenerator interface for use in your param block.


To work around this limitation, use a [ValidateScript()] attribute:

param(
  [ValidateScript({
      if (-not (Get-Item -ErrorAction Ignore "$_.txt")) { 
        throw "$_ is not the (base) name of a *.txt file in the current dir." 
      }
      return $true
  })]
  [string] $FileName
)

Note that this doesn't give you tab-completion the way that IValidateSetValuesGenerator-based validation would automatically give you.

To also provide tab-completion, additionally use an [ArgumentCompleter()] attribute:

param(
  [ValidateScript({
      if (-not (Get-Item -ErrorAction Ignore "$_.txt")) { 
        throw "$_ is not the (base) name of a *.txt file in the current dir." 
      }
      return $true
  })]
  [ArgumentCompleter({ 
    param($cmd, $param, $wordToComplete) 
    (Get-Item "$wordToComplete*.txt").BaseName
  })]
  [string] $FileName
)
like image 160
mklement0 Avatar answered Nov 21 '25 07:11

mklement0



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!