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).
CodePudding user response:
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 (leavingusing
statements aside).This precludes defining a custom
class
that implements theIValidateSetValuesGenerator
interface for use in yourparam
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
)