ValidateSet with class does not work
See original GitHub issuePrerequisites
- Write a descriptive title.
- Make sure you are able to repro it on the latest released version
- Search the existing issues.
- Refer to the FAQ.
- Refer to Differences between Windows PowerShell 5.1 and PowerShell.
Steps to reproduce
Create two files in a directory.
test.ps1
using module './testvalidate.psm1'
param
(
[Parameter(Mandatory)]
[ValidateSet([TestValidate])]
[string]$foo
)
testvalidate.psm1
class TestValidate : System.Management.Automation.IValidateSetValuesGenerator
{
[String[]] GetValidValues()
{
$values = @()
$values += 'bar'
$values += 'baz'
return $values
}
}
Expected behavior
cmdlet test.ps1 at command pipeline position 1
Supply values for the following parameters:
foo:
Actual behavior
InvalidOperation: E:\Software development\Royalty Calculator\trunk.powershell\test.ps1:6
Line |
6 | [ValidateSet([TestValidate])]
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Unable to find type [TestValidate].
Error details
Exception :
Type : System.Management.Automation.RuntimeException
ErrorRecord :
Exception :
Type : System.Management.Automation.ParentContainsErrorRecordException
Message : Unable to find type [TestValidate].
HResult : -2146233087
TargetObject : [ValidateSet([TestValidate])]
CategoryInfo : InvalidOperation: ([ValidateSet([TestValidate])]:AttributeAst) [], ParentContainsErrorRecordException
FullyQualifiedErrorId : TypeNotFound
InvocationInfo :
ScriptLineNumber : 6
OffsetInLine : 5
HistoryId : -1
ScriptName : E:\Software development\Royalty Calculator\trunk.powershell\test.ps1
Line : [ValidateSet([TestValidate])]
PositionMessage : At E:\Software development\Royalty Calculator\trunk.powershell\test.ps1:6 char:5
+ [ValidateSet([TestValidate])]
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PSScriptRoot : E:\Software development\Royalty Calculator\trunk.powershell
PSCommandPath : E:\Software development\Royalty Calculator\trunk.powershell\test.ps1
CommandOrigin : Internal
ScriptStackTrace : at <ScriptBlock>, <No file>: line 1
TargetSite :
Name : NewValidateSetAttribute
DeclaringType : System.Management.Automation.Language.Compiler, System.Management.Automation, Version=7.3.4.500, Culture=neutral, PublicKeyToken=31bf3856ad364e35
MemberType : Method
Module : System.Management.Automation.dll
Message : Unable to find type [TestValidate].
Data : System.Collections.ListDictionaryInternal
Source : System.Management.Automation
HResult : -2146233087
StackTrace :
at System.Management.Automation.Language.Compiler.NewValidateSetAttribute(AttributeAst ast)
at System.Management.Automation.Language.Compiler.GetAttribute(AttributeAst attributeAst)
at System.Management.Automation.Language.Compiler.GetRuntimeDefinedParameter(ParameterAst parameterAst, Boolean& customParameterSet, Boolean& usesCmdletBinding)
at System.Management.Automation.Language.Compiler.GetParameterMetaData(ReadOnlyCollection`1 parameters, Boolean automaticPositions, Boolean& usesCmdletBinding)
at System.Management.Automation.CompiledScriptBlockData.InitializeMetadata()
at System.Management.Automation.CompiledScriptBlockData.Compile(Boolean optimized)
at System.Management.Automation.PSScriptCmdlet..ctor(ScriptBlock scriptBlock, Boolean useNewScope, Boolean fromScriptFile, ExecutionContext context)
at System.Management.Automation.CommandProcessor.Init(IScriptCommandInfo scriptCommandInfo)
at System.Management.Automation.CommandDiscovery.GetScriptAsCmdletProcessor(IScriptCommandInfo scriptCommandInfo, ExecutionContext context, Boolean useNewScope, Boolean fromScriptFile, SessionStateInternal sessionState)
at System.Management.Automation.CommandDiscovery.CreateCommandProcessorForScript(ExternalScriptInfo scriptInfo, ExecutionContext context, Boolean useNewScope, SessionStateInternal sessionState)
at System.Management.Automation.CommandDiscovery.CreateScriptProcessorForSingleShell(ExternalScriptInfo scriptInfo, ExecutionContext context, Boolean useLocalScope, SessionStateInternal sessionState)
at System.Management.Automation.CommandDiscovery.LookupCommandProcessor(CommandInfo commandInfo, CommandOrigin commandOrigin, Nullable`1 useLocalScope, SessionStateInternal sessionState)
at System.Management.Automation.CommandDiscovery.LookupCommandProcessor(String commandName, CommandOrigin commandOrigin, Nullable`1 useLocalScope)
at System.Management.Automation.ExecutionContext.CreateCommand(String command, Boolean dotSource)
at System.Management.Automation.PipelineOps.AddCommand(PipelineProcessor pipe, CommandParameterInternal[] commandElements, CommandBaseAst commandBaseAst, CommandRedirection[] redirections, ExecutionContext context)
at System.Management.Automation.PipelineOps.InvokePipeline(Object input, Boolean ignoreInput, CommandParameterInternal[][] pipeElements, CommandBaseAst[] pipeElementAsts, CommandRedirection[][] commandRedirections, FunctionContext funcContext)
at System.Management.Automation.Interpreter.ActionCallInstruction`6.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
TargetObject : [ValidateSet([TestValidate])]
CategoryInfo : InvalidOperation: ([ValidateSet([TestValidate])]:AttributeAst) [], RuntimeException
FullyQualifiedErrorId : TypeNotFound
InvocationInfo :
ScriptLineNumber : 6
OffsetInLine : 5
HistoryId : -1
ScriptName : E:\Software development\Royalty Calculator\trunk.powershell\test.ps1
Line : [ValidateSet([TestValidate])]
PositionMessage : At E:\Software development\Royalty Calculator\trunk.powershell\test.ps1:6 char:5
+ [ValidateSet([TestValidate])]
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PSScriptRoot : E:\Software development\Royalty Calculator\trunk.powershell
PSCommandPath : E:\Software development\Royalty Calculator\trunk.powershell\test.ps1
CommandOrigin : Internal
ScriptStackTrace : at <ScriptBlock>, <No file>: line 1
Environment data
Name Value
---- -----
PSVersion 7.3.4
PSEdition Core
GitCommitId 7.3.4
OS Microsoft Windows 10.0.19045
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
Visuals
No response
Issue Analytics
- State:
- Created 4 months ago
- Comments:10 (2 by maintainers)
Top Results From Across the Web
PowerShell ValidateSet: Choosing from a List
A ValidateSet list is a comma-separated list of string values, wrapped in single or double-quotes. Adding a ValidateSet attribute to a script or ......
Read more >Couldn't use predefined array inside Validateset - Powershell
ps1 file) that is invoked directly, i.e. a script that starts with a param(...) block. The above approaches wouldn't work, because any class...
Read more >ValidateSet Attribute Declaration - PowerShell
The cmdlet is run only if the parameter argument matches an element in the set. If no match is found, an error is...
Read more >PowerShell parameter validate set and removing already ...
I have a function with several parameters defined. One of the parameters is a validate set consisting of 3 items. This works as...
Read more >The classy way to complete and validate PowerShell ...
ValidateSets define allowed choices, if the value entered is not in the set, PowerShell will throw an error saying “valid values are …”....
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
There is a workaround, but it is somewhat cumbersome: It relies on the fact that referencing types in script blocks used in parameter attributes happens at runtime, so the imported type is then already available:
The unfortunate side effect of using
ArgumentCompleter
with a script block (rather than with anIArgumentCompleter
-implementing class) is that if what the user typed doesn’t match any of the valid values, the default file-name completion behavior kicks in; see:I would expect so. For tab completion to work I expect it needs to have access to all the classes to do the value matching. If all the command line interpreter does is read the param stanza then it won’t have enough information. I don’t expect that tab-completion is done by actually running the script.
about_Functions_Argument_Completion
Can you not do something like their example?
The auto-completion offered both ‘hello’ and ‘world’ as options
This also errors when you try and assign ‘bye’ to $Message