Reputation: 182
I have a module with a lot of advanced functions. I need to use a long list of ValidateSet parameters. I would like to put the whole list of possible parameters in an array and then use that array in the functions themselves. How can I pull the list of the whole set from an array?
New-Variable -Name vars3 -Option Constant -Value @("Banana","Apple","PineApple")
function TEST123 {
param ([ValidateScript({$vars3})]
$Fruit)
Write-Host "$Fruit"
}
The problem is that when I use the function it doesn't pull the content from the constant.
TEST123 -Fruit
If I specify the indexed value of the constant then it works.
TEST123 -Fruit $vars3[1]
It returns Apple.
Upvotes: 1
Views: 5181
Reputation: 326
I am not sure exactly what your use case is, but another possibility if you're using PowerShell 5.x, or newer, is to create a class, or if you're using an older version you could embed a little C# in your code to create an Enum that you can use:
Add-Type -TypeDefinition @"
public enum Fruit
{
Strawberry,
Orange,
Apple,
Pineapple,
Kiwi,
Blueberry,
Raspberry
}
"@
Function TestMe {
Param(
[Fruit]$Fruit
)
Write-Output $Fruit
}
Upvotes: 1
Reputation: 16086
You are misunderstanding how ValidateScript ...
ValidateScript Validation Attribute
The ValidateScript attribute specifies a script that is used to validate a parameter or variable value. PowerShell pipes the value to the script, and generates an error if the script returns $false or if the script throws an exception.
When you use the ValidateScript attribute, the value that is being validated is mapped to the $_ variable. You can use the $_ variable to refer to the value in the script.
... works. As the others have pointed out thus far. You are not using a script you are using a static variable.
To get what I believe you are after, you would do it, this way.
(Note, that Write- is also not needed, since output to the screen is the default in PowerShell. Even so, avoid using Write-Host, except for in targeted scenarios, like using color screen output. Yet, even then, you don't need it for that either. There are several cmdlets that can be used, and ways of getting color with more flexibility. See these listed MS powershelgallery.com modules)*
Find-Module -Name '*Color*'
Tweaking your code you posted, and incorporating what Ansgar Wiechers, is showing you.
$ValidateSet = @('Banana','Apple','PineApple') # (Get-Content -Path 'E:\Temp\FruitValidationSet.txt')
function Test-LongValidateSet
{
[CmdletBinding()]
[Alias('tlfvs')]
Param
(
[Validatescript({
if ($ValidateSet -contains $PSItem) {$true}
else { throw $ValidateSet}})]
[String]$Fruit
)
"The selected fruit was: $Fruit"
}
# Results - will provide intellisense for the target $ValidateSet
Test-LongValidateSet -Fruit Apple
Test-LongValidateSet -Fruit Dog
# Results
The selected fruit was: Apple
# and on failure, spot that list out. So, you'll want to decide how to handle that
Test-LongValidateSet -Fruit Dog
Test-LongValidateSet : Cannot validate argument on parameter 'Fruit'. Banana Apple PineApple
At line:1 char:29
Just add to the text array / file but this also means, that file has to be on every host you use this code on or at least be able to reach a UNC share to get to it.
Now, you can use the other documented "dynamic parameter validate set". the Lee_Daily points you to lookup, but that is a bit longer in the tooth to get going.
Example:
function Test-LongValidateSet
{
[CmdletBinding()]
[Alias('tlfvs')]
Param
(
# Any other parameters can go here
)
DynamicParam
{
# Set the dynamic parameters' name
$ParameterName = 'Fruit'
# Create the dictionary
$RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
# Create the collection of attributes
$AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
# Create and set the parameters' attributes
$ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute
$ParameterAttribute.Mandatory = $true
$ParameterAttribute.Position = 1
# Add the attributes to the attributes collection
$AttributeCollection.Add($ParameterAttribute)
# Generate and set the ValidateSet
$arrSet = Get-Content -Path 'E:\Temp\FruitValidationSet.txt'
$ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($arrSet)
# Add the ValidateSet to the attributes collection
$AttributeCollection.Add($ValidateSetAttribute)
# Create and return the dynamic parameter
$RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection)
$RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter)
return $RuntimeParameterDictionary
}
begin
{
# Bind the parameter to a friendly variable
$Fruit = $PsBoundParameters[$ParameterName]
}
process
{
# Your code goes here
$Fruit
}
}
# Results - provide intellisense for the target $arrSet
Test-LongValidateSet -Fruit Banana
Test-LongValidateSet -Fruit Cat
# Results
Test-LongValidateSet -Fruit Banana
Banana
Test-LongValidateSet -Fruit Cat
Test-LongValidateSet : Cannot validate argument on parameter 'Fruit'. The argument "Cat" does not belong to the set "Banana,Apple,PineApple"
specified by the ValidateSet attribute. Supply an argument that is in the set and then try the command again.
At line:1 char:29
Again, just add to the text to the file, and again, this also means, that file has to be on every host you use this code on or at least be able to reach a UNC share to get to it.
Upvotes: 1