Custom Select Input using ValidateSet with Array

I’m trying to pull the Names of Departmental OU’s that house Security Groups and create a Select (Drop Down) Input for each department. Every method I’ve tried for this leads to the below error when I restart the Dashboard.

I’ve tried writing the script block of the ValidateSet as a for loop, foreach-object, and my last attempt was cache the Get-ADOrganizationalUnit one liner as an array and convert it to string and comma seperate it like below:

[array]$Cache:groupNames = Get-ADOrganizationalUnit -LDAPFilter '(name=*)' -SearchBase 'OU=OU1,OU=Groups,DC=domain,DC=domain,DC=local' -SearchScope OneLevel | Select-Object -ExpandProperty name 
[string]$Cache:grpNms = $groupNames -join ","

But no luck… Has anyone ever got this to work successfully or is it even possible within UD to pull something like this off?

Full {Current} Code for the Start of this Tool:

[array]$Cache:groupNames = Get-ADOrganizationalUnit -LDAPFilter '(name=*)' -SearchBase 'OU=OU1,OU=Groups,DC=domain,DC=domain,DC=local' -SearchScope OneLevel | Select-Object -ExpandProperty name 
[string]$Cache:grpNms = $groupNames -join ","
New-UDCard @Colors -Title "Select Dept From Drop Down." -Content {
    New-UDInput -Title "Departments" -Endpoint{                           
        param ([ValidateSet({$Cache:grpNms})]$Department)
        New-UDInputAction -Toast "You selected: $Department"


I haven’t tested this, but I would try using a ValidateScript instead of a ValidateSet. Something like:

param ([ValidateScript({$_ -in $Cache:groupNames})]$Department)

That Cleared the error but it doesn’t build the drop-down list for the selected input it only has a text input when using ValidateScript. It does seem to hold the variable values though because if I enter one of the correct values it gives the toast message and errors out when something outside of it is entered. I wonder if the cmdlet is written to only use ValidateSet for the Selected Input?

That’s a shortcoming of PowerShell, not UD. You’ll see the same behavior when using ValidateScript vs ValidateSet in a function definition. I.e. - ValidateScript does not feed into Intellisense and tab completion. To get dynamic tab completion in a function, you would have to define dynamic parameters. I doubt dynamic parameters are an option here.

1 Like

Yeah, Dynamic Params would be way more work than it would be worth here I think. That’s just how it goes sometimes. Ill just come up with a different way of handling this part of the tool. Thank you for your input @MadWithPowerShell.

Discard the last message :slight_smile: this should work, only downside is that spaces are needed to be replaced.

So for the Add-Type is that on a completely different line in your above code? Also what are you feeding to the -TypeDefinition?

When I run your code currently I’m getting the following error:

Add-Type : Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 
'TypeDefinition'. Specified method is not supported.
At line:2 char:26
+ Add-Type -TypeDefinition $Cache:groupNames
+                          ~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument: (:) [Add-Type], ParameterBindingException
+ FullyQualifiedErrorId : 

here :slight_smile:

1 Like

@McAndersDK That worked like a charm! Thank you so much. 100% would have never figured that out.

Just so I understand what is going on, the Add-Type -TypeDefinition is just changing the Array Variable over to a comma-separated list that will work AS the ValidatedSet?

I really appreciate your help here.

Glad it worked for you :slight_smile:

No, we are creating a “herestring”
That we use as a Type Definition, and use the function add-type to make it a System Type we can then use.
well we are dynamic making an Enum :slight_smile:

1 Like

@aggiebeckett, @McAndersDK,

Intrigued by the challenge, I looked through all of unicode and found three characters that appear to be spaces to humans, but are officially designated as letters, so they are legal in .Net in enum names. Unfortunately, all three are a bit wider than normal spaces, so it does look a little odd, but you can substitute one of these for spaces instead of underscores. The easiest to remember character is hex 0x1160. (All three are labeled as Hangul filler characters.)

And if you are going to dynamically build C# code to execute, you might as well dynamically build PowerShell code to do the same thing. The first -replace filters out any character that isn’t a letter (in any language), a space, or an underscore. This protects you against code injection. No matter what the values of the group names, the Invoke-Expression can do nothing but define an enum. The second -replace substitutes the non-space space for any regular space. Then substitute them back again when used at the end.

[array]$Cache:GroupNames = Get-ADOrganizationalUnit -LDAPFilter '(name=*)' -SearchBase 'OU=OU1,OU=Groups,DC=domain,DC=domain,DC=local' -SearchScope OneLevel |
    Select-Object -ExpandProperty name

$DefEnum = "enum Department {{{0}}} " -f ( $Cache:GroupNames.ForEach{ $_ -replace '[^\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}\p{Lm} _]', '' -replace ' ', [char]0x1160 } -join ';' )
Invoke-Expression $DefEnum

New-UDCard -Title "Select Dept From Drop Down." -Content {
    New-UDInput -Title "Departments" -Endpoint{
        Param ( [Department]$Department )
            $Dept = $Department -replace [char]0x1160, ' '
            New-UDInputAction -Toast "You selected: $Dept" } }

Tim Curwick

1 Like