Skip to content

Getting error "Unable to find type" when using IValidateSetValuesGenerator in a PowerShell module #5661

@LethiferousMoose

Description

@LethiferousMoose

Steps to reproduce

  1. Create a module file (*.psm1) and add the following code block.
  2. Attempt to call Test-ValidateSet -Item 'Hello' from PowerShell
class ValidateSetTest : System.Management.Automation.IValidateSetValuesGenerator
{
    [string[]] GetValidValues()
    {
        return 'Hello', 'World'
    }
}

function Test-ValidateSet
{
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [ValidateSet([ValidateSetTest])]
        [string[]]
        $Item
    )
    $Item
}

Expected behavior

Hello

Actual behavior

Unable to find type [ValidateSetTest].
At C:\PSTest\PSTest.psm1:1364 char:9
+         [ValidateSet([ValidateSetTest])]
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidOperation: ([ValidateSet([ValidateSetTest])]:AttributeAst) [], RuntimeException
+ FullyQualifiedErrorId : TypeNotFound

Environment data

Name                           Value
----                           -----
PSVersion                      6.0.0-rc
PSEdition                      Core
GitCommitId                    v6.0.0-rc
OS                             Microsoft Windows 10.0.15063
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

This happens because the defined class is only known to the module. In order for this feature to work currently "Using Module <ModuleName>" must be called from PowerShell to load the class definitions or a second option is to define a *.ps1 file that contains your class definitions, then in the *.psd1 file, add that script path to the ScriptsToProcess attribute list.

The advantages of modifying the manifest file is that it does not require anything from the end user to get the module to work, however since the class definition lives in an external file, that also means it cannot reference of the internal workings of the module. On the flip side, "using module" allows for the class to remain within the module, but also mean a script must be written or end user action must be taken to bring the class definition into the current session. Additionally this will load any internal class definitions inside the module into their session as well.

Without doing something around these lines, this new feature #3744 cannot be used in modules and only works if you dot-source a script file. As this feature was added to get around having to create dynamic parameters to simply add dynamic ValidateSet values, I feel like modules were the intended use case for this feature as they typically are responsible for exposing multiple functions to the end user whereas scripts as generally just called as a script.

Also note that when using the workaround solutions mentioned above, it also exposes those class definitions to the end users session, something that they really should not care about.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue-BugIssue has been identified as a bug in the productResolution-FixedThe issue is fixed.WG-Languageparser, language semantics

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions