Reputation: 23
I want to validate user inputs in a script which sets the attributes Company, Department, and Office in Active Directory.
This is what I've got so far:
$ApprovedLocations = #A table with known Company,Department,Office values
Class Company : System.Management.Automation.IValidateSetValuesGenerator {
[String[]] GetValidValues(){
return $global:ApprovedLocations.Company
}
}
Class Department : System.Management.Automation.IValidateSetValuesGenerator {
[String[]] GetValidValues(){
return $global:ApprovedLocations.Department
}
}
Class Office : System.Management.Automation.IValidateSetValuesGenerator {
[String[]] GetValidValues(){
return $global:ApprovedLocations.Office
}
}
function Set-AttributeTest{
param (
[Parameter(Mandatory)][string]$Name,
[ValidateSet([Company])][string]$Company,
[ValidateSet([Department])][string]$Department,
[ValidateSet([Office])][string]$Office
)
#Do stuff
}
This works to prevent typos. But since not all companies have the same departments and offices I'd like the ValidateSet to allow different values depending on previous parameter. E.g. only allow office and department combinations which actually exist at the different companies.
Example:
Company A
|-- HR
| |-- Office A
| |-- Office B
|
|-- IT
|-- Office C
|-- Office D
Company B
|-- Design
| |-- Office E
| |-- Office F
|
|-- Finance
// ...etc
Is there a way to do this with parameters in Powershell or should I rethink the entire thing?
Upvotes: 2
Views: 485
Reputation: 4634
There are variants:
Example using Dynamic Parameters for single dynamic parameter.
$global:CompanyDepts = @{
'Contoso' = @('Sales', 'IT')
'Adatum' = @('HR', 'Shipping')
}
function Test-DynParam {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[ValidateSet('Contoso', 'Adatum')]
[String]$Company
)
DynamicParam {
if (-not [String]::IsNullOrWhiteSpace($Company) -and $global:CompanyDepts.ContainsKey($Company) )
{
$attrDept = [System.Management.Automation.ParameterAttribute]::new()
$attrDept.ParameterSetName = 'CompanySet'
$attrDept.Mandatory = $true
$attrDeptValidation = [System.Management.Automation.ValidateSetAttribute]::new([String[]]$global:CompanyDepts[$Company])
$attributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
$attributeCollection.Add($attrDept)
$attributeCollection.Add($attrDeptValidation )
$param = [System.Management.Automation.RuntimeDefinedParameter]::new('Department', [String], $attributeCollection)
$paramDict = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
$paramDict.Add('Department', $param)
return $paramDict
}
}
process {
$PSBoundParameters.Keys | % { Write-Host "$($_)=$($PSBoundParameters[$_])" }
}
}
Note that you SHOULD help users to achieve best usage expirience, so remember that one user can start typing My-Cmdlet -Company ...
presuming Department
autocomplete, and another user prefer typing My-Cmdlet -Department ...
presuming Company
autocomplete, so there sjhould be a combination of ParameterSets and DynamicParams
Upvotes: 3