Powershell Data Malformed with Splatting - powershell

I am using a custom function that imports data using an API. The function requires several different parameters, which I am currently defining with one $Params hashtable. From there I am adding other parameters that may or may not be added based on certain conditions. I have noticed that storing all parameters in the hashtable is not working properly, but will only work if particularly specified in the function call.
A basic version of the code that does not currently work is:
$ExtraParam = 'ccc'
$Params = #{
Par1 = 'aaa'
Par2 = 'bbb'
}
$Params.Par3 = $ExtraParam
Import-APIData #Params
The API is returning the following error message:
{"errorId":"error.request.invalidRepresentation.malformed","errorCode":0,"message":"Invalid parameter value was specified."}
However, if I run the following code it works perfectly fine:
$ExtraParam = 'abc'
$Params = #{
Par1 = '123'
Par2 = '456'
}
Import-APIData #Params -Par3 $ExtraParam
I have verified that the parameters coming into the function are all of the correct type. The custom function I am calling is proprietary so I cannot share the entire function, but I was just wondering if there was anything that would reformat the parameters in the hashtable as opposed to explicitly calling it in the function call. Given that the two chunks of code are essentially the same I am hoping someone can point out some fundamental difference that may cause the top portion to not work.
Per a request of a commenter, here is the actual function. The _CallAPI function at the bottom is what actually calls the API. I will not be able to share that, but using the $Params output right above it (commented out in the code) may hopefully be enough to troubleshoot.
function Update-ICUser {
<#
.SYNOPSIS
Updates user on a Gensys ICWS server.
.PARAMETER ICSession
string ICSession. ICSession to update a user.
.PARAMETER Id
string Id. Id of the user to update.
.PARAMETER InputObject
object InputObject. Full IC User is needed.
.PARAMETER Argument
string Argument. Any query string parameters associated with the Api call.
.Example
$ICSession = New-ICSession -ComputerName server1 -Credential $Credential
Get-ICUser -Id user1 -Full |Update-ICUser -ICSession $ICsession -Extension 1234
Example 1: Update a user's extension.
#>
[CmdletBinding()]
param (
[Parameter(Mandatory,
Position = 0)]
[ICSession]$ICSession,
[Parameter(Mandatory,
ValueFromPipeline,
ParameterSetName = 'InputObject',
Position = 1)]
[object]$InputObject,
[Parameter(Mandatory,
ParameterSetName = 'Manual',
Position = 2)]
[string]$Id,
[Parameter(ParameterSetName = 'Manual',
Position = 3)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$DisplayName,
[Parameter(ParameterSetName = 'Manual',
Position = 4)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$OutboundAni,
[Parameter(ParameterSetName = 'Manual',
Position = 5)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$Title,
[Parameter(ParameterSetName = 'Manual',
Position = 6)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$OfficeLocation,
[Parameter(ParameterSetName = 'Manual',
Position = 7)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$Notes,
[Parameter(ParameterSetName = 'Manual',
Position = 8)]
[Parameter(ParameterSetName = 'InputObject')]
[int]$Cost = 0,
[Parameter(ParameterSetName = 'Manual',
Position = 9)]
[Parameter(ParameterSetName = 'InputObject')]
[bool]$AutoAnswerAcdInteractions = $false,
[Parameter(ParameterSetName = 'Manual',
Position = 10)]
[Parameter(ParameterSetName = 'InputObject')]
[bool]$AutoAnswerNonAcdInteractions = $true,
[Parameter(ParameterSetName = 'Manual',
Position = 11)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$ApplicationId = 'InteractionDesktop',
[Parameter(ParameterSetName = 'Manual',
Position = 12)]
[Parameter(ParameterSetName = 'InputObject')]
[bool]$ExcludeFromDirectory = $false,
[Parameter(ParameterSetName = 'Manual',
Position = 13)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$Extension,
[Parameter(ParameterSetName = 'Manual',
Position = 14)]
[Parameter(ParameterSetName = 'InputObject')]
[bool]$FaxCapability = $false,
[Parameter(ParameterSetName = 'Manual',
Position = 15)]
[Parameter(ParameterSetName = 'InputObject')]
[bool]$OutlookIntegrationEnabled = $false,
[Parameter(ParameterSetName = 'Manual',
Position = 16)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$FirstName,
[Parameter(ParameterSetName = 'Manual',
Position = 17)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$LastName,
[Parameter(ParameterSetName = 'Manual',
Position = 18)]
[Parameter(ParameterSetName = 'InputObject')]
[string[]]$WorkgroupList,
[Parameter(ParameterSetName = 'Manual',
Position = 19)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$DepartmentName,
[Parameter(ParameterSetName = 'Manual',
Position = 20)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$City,
[Parameter(ParameterSetName = 'Manual',
Position = 21)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$PostalCode,
[Parameter(ParameterSetName = 'Manual',
Position = 22)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$State,
[Parameter(ParameterSetName = 'Manual',
Position = 23)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$StreetAddress,
[Parameter(ParameterSetName = 'Manual',
Position = 24)]
[Parameter(ParameterSetName = 'InputObject')]
[int]$HomeSite,
[Parameter(ParameterSetName = 'Manual',
Position = 25)]
[Parameter(ParameterSetName = 'InputObject')]
[string[]]$LicenseList,
[Parameter(ParameterSetName = 'Manual',
Position = 26)]
[Parameter(ParameterSetName = 'InputObject')]
[string[]]$RoleList
)
Try {
if ($InputObject) {
$User = $InputObject
$Id = $InputObject.configurationId.id
}
else {
$User = Get-ICUser -ICSession $ICSession -Id $Id -Full
}
'Id','InputObject','ICSession' |Foreach-Object {
$PSBoundParameters.Remove($PSItem) |Out-Null
}
$PSBoundParameters.GetEnumerator() |Foreach-Object {
if ($PSItem.Key -in ('Title','DepartmentName','City','State','StreetAddress','FirstName','LastName','Notes')) {
if ($PSItem.Key -in ('State','FirstName','LastName')) {
$Key = switch ($PSItem.Key) {
'State' {'stateOrProvince'}
'FirstName' {'givenName'}
'LastName' {'surName'}
}
}
else {
$Key = $PSItem.Key
}
$User.personalInformationProperties.$Key = $PSItem.Value
}
elseif ($PSItem.Key -in ('WorkgroupList','LicenseList','RoleList')) {
$Key = $PSItem.Key
if ($Key = 'WorkgroupList' -and $WorkgroupList) {
[array]$Value = Get-ICWorkgroup -ICSession $SessionKey -Id $WorkgroupList
$User.Workgroups = $Value
}
if ($Key = 'LicenseList' -and $LicenseList) {
$Value = #((Get-ICLicenseAllocation -ICSession $SessionKey -Id $LicenseList).configurationId)
if ($User.licenseProperties.PSobject.Properties.name -match 'additionalLicenses') {
$User.licenseProperties.additionalLicenses = $Value
}
else {
$User.licenseProperties | Add-Member -MemberType NoteProperty -Name 'additionalLicenses' -Value $Value -Force
}
}
if ($Key = 'RoleList' -and $RoleList) {
[array]$Value = Get-ICRole -ICSession $SessionKey -Id $RoleList
if ($User.roles.PSobject.Properties.name -match 'actualValue') {
$User.Roles.actualValue = $Value
}
else {
$User.roles | Add-Member -MemberType NoteProperty -Name 'actualValue' -Value $Value -Force
}
}
}
else {
$Key = $PSItem.Key
$Value = $PSItem.Value
$User |Add-Member -MemberType NoteProperty -Name $Key -Value $Value -Force
}
}
$Body = $User |ConvertTo-Json -Depth 5
$Params = #{
Area = $Configuration.Area.Configuration
Resource = $Configuration.Resource.Users
ICSession = $ICSession
Id = $Id
Method = 'Put'
ContentType = 'application/json'
Body = $Body
}
# $Params
_CallApi #Params
}
Catch {
_ExceptionError
}
}
I will also provide everything on the console. In this example the $AutoAnswerAcd parameter is the one that is failing, but I have gotten it to fail and work by adding/removing other parameters. I have not detected a pattern that makes it fail yet, other than that it always works outside of the splat. You can see this pattern below.
PS C:\> $SessionKey = New-ICSession -ComputerName $server -Credential $Credential
PS C:\> $Params = #{
>> ICSession = $SessionKey
>> Id = 'tautomation'
>> WorkgroupList = "MultiSite-UserSpan"
>> RoleList = "Business User"
>> LicenseList = "I3_ACCESS_RECORDER"
>> DepartmentName = "Infr & Ops"
>> Title = "Process Automation Engineer"
>> OfficeLocation = "Remote"
>> AutoAnswerAcdInteractions = $true
>> }
PS C:\> Update-ICUser #Params
Exception: C:\Repos\ICTools\Code\Private\_ExceptionError.ps1:10
Line |
10 | throw "$($Exception)`n$($Exception.Exception.Message)"
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| {"errorId":"error.request.invalidRepresentation.malformed","errorCode":0,"message":"Invalid parameter value was specified."} Response status code does not indicate
| success: 400 (Bad Request). {"errorId":"error.request.invalidRepresentation.malformed","errorCode":0,"message":"Invalid parameter value was specified."} Response status
| code does not indicate success: 400 (Bad Request).
PS C:\> $Params = #{
>> ICSession = $SessionKey
>> Id = 'tautomation'
>> WorkgroupList = "MultiSite-UserSpan"
>> RoleList = "Business User"
>> LicenseList = "I3_ACCESS_RECORDER"
>> DepartmentName = "Infr & Ops"
>> Title = "Process Automation Engineer"
>> OfficeLocation = "Remote"
>> }
PS C:\> Update-ICUser #Params
id uri
-- ---
tautomation /configuration/users/tautomation
PS C:\> Update-ICUser #Params -AutoAnswerAcdInteractions $true
id uri
-- ---
tautomation /configuration/users/tautomation
PS C:\>
Thanks!

Ok, so think I've found what's happening.
Firstly, here's an instrumented version of your code that gives some log output as it runs - that'll help see where it's going wrong...
function Update-ICUser {
[CmdletBinding()]
param (
[Parameter(Mandatory,
Position = 0)]
[string]$ICSession,
[Parameter(Mandatory,
ValueFromPipeline,
ParameterSetName = 'InputObject',
Position = 1)]
[object]$InputObject,
[Parameter(Mandatory,
ParameterSetName = 'Manual',
Position = 2)]
[string]$Id,
[Parameter(ParameterSetName = 'Manual',
Position = 3)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$DisplayName,
[Parameter(ParameterSetName = 'Manual',
Position = 4)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$OutboundAni,
[Parameter(ParameterSetName = 'Manual',
Position = 5)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$Title,
[Parameter(ParameterSetName = 'Manual',
Position = 6)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$OfficeLocation,
[Parameter(ParameterSetName = 'Manual',
Position = 7)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$Notes,
[Parameter(ParameterSetName = 'Manual',
Position = 8)]
[Parameter(ParameterSetName = 'InputObject')]
[int]$Cost = 0,
[Parameter(ParameterSetName = 'Manual',
Position = 9)]
[Parameter(ParameterSetName = 'InputObject')]
[bool]$AutoAnswerAcdInteractions = $false,
[Parameter(ParameterSetName = 'Manual',
Position = 10)]
[Parameter(ParameterSetName = 'InputObject')]
[bool]$AutoAnswerNonAcdInteractions = $true,
[Parameter(ParameterSetName = 'Manual',
Position = 11)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$ApplicationId = 'InteractionDesktop',
[Parameter(ParameterSetName = 'Manual',
Position = 12)]
[Parameter(ParameterSetName = 'InputObject')]
[bool]$ExcludeFromDirectory = $false,
[Parameter(ParameterSetName = 'Manual',
Position = 13)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$Extension,
[Parameter(ParameterSetName = 'Manual',
Position = 14)]
[Parameter(ParameterSetName = 'InputObject')]
[bool]$FaxCapability = $false,
[Parameter(ParameterSetName = 'Manual',
Position = 15)]
[Parameter(ParameterSetName = 'InputObject')]
[bool]$OutlookIntegrationEnabled = $false,
[Parameter(ParameterSetName = 'Manual',
Position = 16)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$FirstName,
[Parameter(ParameterSetName = 'Manual',
Position = 17)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$LastName,
[Parameter(ParameterSetName = 'Manual',
Position = 18)]
[Parameter(ParameterSetName = 'InputObject')]
[string[]]$WorkgroupList,
[Parameter(ParameterSetName = 'Manual',
Position = 19)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$DepartmentName,
[Parameter(ParameterSetName = 'Manual',
Position = 20)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$City,
[Parameter(ParameterSetName = 'Manual',
Position = 21)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$PostalCode,
[Parameter(ParameterSetName = 'Manual',
Position = 22)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$State,
[Parameter(ParameterSetName = 'Manual',
Position = 23)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$StreetAddress,
[Parameter(ParameterSetName = 'Manual',
Position = 24)]
[Parameter(ParameterSetName = 'InputObject')]
[int]$HomeSite,
[Parameter(ParameterSetName = 'Manual',
Position = 25)]
[Parameter(ParameterSetName = 'InputObject')]
[string[]]$LicenseList,
[Parameter(ParameterSetName = 'Manual',
Position = 26)]
[Parameter(ParameterSetName = 'InputObject')]
[string[]]$RoleList
)
if ($InputObject) {
$User = $InputObject
$Id = $InputObject.configurationId.id
}
else {
$User = [pscustomobject] #{
personalInformationProperties = [pscustomobject] #{
DepartmentName = $null
Title = $null
}
licenseProperties = [pscustomobject] #{}
roles = [pscustomobject] #{}
Workgroups = $null
}
#Get-ICUser -ICSession $ICSession -Id $Id -Full
}
#write-host "user = '$($User |ConvertTo-Json -Depth 5)'"
'Id','InputObject','ICSession' |Foreach-Object {
$PSBoundParameters.Remove($PSItem) |Out-Null
}
$PSBoundParameters.GetEnumerator() |Foreach-Object {
write-host "processing key '$($PSItem.Key)'"
if ($PSItem.Key -in ('Title','DepartmentName','City','State','StreetAddress','FirstName','LastName','Notes')) {
if ($PSItem.Key -in ('State','FirstName','LastName')) {
$Key = switch ($PSItem.Key) {
'State' {'stateOrProvince'}
'FirstName' {'givenName'}
'LastName' {'surName'}
}
}
else {
$Key = $PSItem.Key
}
$User.personalInformationProperties.$Key = $PSItem.Value
}
elseif ($PSItem.Key -in ('WorkgroupList','LicenseList','RoleList')) {
$Key = $PSItem.Key
if ($Key = 'WorkgroupList' -and $WorkgroupList) {
write-host " WorkgroupList - casting to array"
#$Value = #( Get-ICWorkgroup -ICSession $SessionKey -Id $WorkgroupList )
[array] $Value = #()
#$User.Workgroups = $Value
}
if ($Key = 'LicenseList' -and $LicenseList) {
write-host " LicenseList - casting to array"
#$Value = #((Get-ICLicenseAllocation -ICSession $SessionKey -Id $LicenseList).configurationId)
$Value = #()
if ($User.licenseProperties.PSobject.Properties.name -match 'additionalLicenses') {
$User.licenseProperties.additionalLicenses = $Value
}
else {
$User.licenseProperties | Add-Member -MemberType NoteProperty -Name 'additionalLicenses' -Value $Value -Force
}
}
if ($Key = 'RoleList' -and $RoleList) {
write-host " RoleList - casting to array"
#[array]$Value = Get-ICRole -ICSession $SessionKey -Id $RoleList
[array]$Value = #()
if ($User.roles.PSobject.Properties.name -match 'actualValue') {
$User.Roles.actualValue = $Value
}
else {
$User.roles | Add-Member -MemberType NoteProperty -Name 'actualValue' -Value $Value -Force
}
}
}
else {
write-host "adding key '$($PSItem.Key)' with value '$($PSItem.Value)'"
write-host " value before is '$($Value.GetType().FullName)'"
$Key = $PSItem.Key
write-host " value after is '$($Value.GetType().FullName)'"
$Value = $PSItem.Value
#write-host ($PSItem.Key | convertto-json)
#write-host ($PSItem.Value | convertto-json)
#write-host $PSItem.Key.GetType().FullNane
#write-host $PSItem.Value.GetType().FullNane
#write-host "user before = '$($User |ConvertTo-Json -Depth 5)'"
$User |Add-Member -MemberType NoteProperty -Name $Key -Value $Value -Force
#write-host "user after = '$($User |ConvertTo-Json -Depth 5)'"
}
}
$Body = $User |ConvertTo-Json -Depth 5
write-host $Body
}
and when you call it with, e.g. this:
$Params = #{
ICSession = "aaa"
Id = 'tautomation'
WorkgroupList = "MultiSite-UserSpan"
RoleList = "Business User"
LicenseList = "I3_ACCESS_RECORDER"
DepartmentName = "Infr & Ops"
Title = "Process Automation Engineer"
OfficeLocation = "Remote"
AutoAnswerAcdInteractions = $true
}
Update-ICUser #Params
you get this output:
processing key 'DepartmentName'
processing key 'OfficeLocation'
adding key 'OfficeLocation' with value 'Remote'
processing key 'Title'
processing key 'WorkgroupList'
WorkgroupList - casting to array
LicenseList - casting to array
RoleList - casting to array
processing key 'AutoAnswerAcdInteractions'
adding key 'AutoAnswerAcdInteractions' with value 'True'
value before is 'System.Object[]'
value after is 'System.Object[]'
processing key 'RoleList'
WorkgroupList - casting to array
LicenseList - casting to array
RoleList - casting to array
processing key 'LicenseList'
WorkgroupList - casting to array
LicenseList - casting to array
RoleList - casting to array
{
"personalInformationProperties": {
"DepartmentName": "Infr & Ops",
"Title": "Process Automation Engineer"
},
"licenseProperties": {
"additionalLicenses": []
},
"roles": {
"actualValue": []
},
"Workgroups": null,
"OfficeLocation": "Remote",
"AutoAnswerAcdInteractions": [
true
]
}
So there's a few things to note:
casting to array
casting to array seems to be getting logged for three parameters (WorkgroupList, RoleList and LicenseList) when processing each of them.
If you look, your code is doing this: if ($Key = 'WorkgroupList' -and $WorkgroupList) but = is an assignment operator, not a comparison operator, so what you really want is if ($Key -eq 'WorkgroupList' -and $WorkgroupList)
It's the same for if ($Key = 'LicenseList' -and $LicenseList) and if ($Key = 'RoleList' -and $RoleList) - change those to -eq as well and that's one bug stomped...
adding key 'AutoAnswerAcdInteractions' with value 'True'
The $Value variable is of type System.Object[] before and after assigning the parameter value. If you look at the previous parameter in the logs you'll see WorkgroupList - casting to array - this is changing the type of $Value to be an array. Any future attempts to assign values will automatically convert the value to an array, so $true becomes [ $true ], which is where your problem is coming from.
Note the same cast is happening in RoleList, but not LicenseList.
Since the order of keys is not guaranteed in a hashtable or $PSBoundParameters, your issue only happens if:
$WorkgroupList or $RoleList are specified in the function call
They happen to be enumerated before $AutoAnswerAcdInteractions
To fix this, refactor WorkgroupList and RoleList to be the same as LicenseList - i.e. instead of:
[array]$Value = <expression>
use the Array subexpression operator:
$Value = #( <expression> )
This will ensure the value stored in the variable is an array without changing the type of the variable for future parameters.
Note that the reason the extra parameter appears to work is it changes the order of the items in $PSBoundParameters. For example:
$Params = #{
ICSession = "aaa"
Id = 'tautomation'
WorkgroupList = "MultiSite-UserSpan"
RoleList = "Business User"
LicenseList = "I3_ACCESS_RECORDER"
DepartmentName = "Infr & Ops"
Title = "Process Automation Engineer"
OfficeLocation = "Remote"
}
Update-ICUser #Params -AutoAnswerAcdInteractions $true
gives this output
processing key 'AutoAnswerAcdInteractions'
adding key 'AutoAnswerAcdInteractions' with value 'True'
processing key 'DepartmentName'
processing key 'Title'
processing key 'WorkgroupList'
WorkgroupList - casting to array
processing key 'RoleList'
RoleList - casting to array
processing key 'LicenseList'
LicenseList - casting to array
processing key 'OfficeLocation'
adding key 'OfficeLocation' with value 'Remote'
value before is 'System.Object[]'
value after is 'System.Object[]'
{
"personalInformationProperties": {
"DepartmentName": "Infr & Ops",
"Title": "Process Automation Engineer"
},
"licenseProperties": {
"additionalLicenses": []
},
"roles": {
"actualValue": []
},
"Workgroups": null,
"AutoAnswerAcdInteractions": true,
"OfficeLocation": [
"Remote"
]
}
Note that AutoAnswerAcdInteractions is processed before any of the paths that change the type of $Value to an array.
Incidentally, the code also works if you omit WorkgroupList and RoleList because $Value never gets changed to an array:
$Params = #{
ICSession = "aaa"
Id = 'tautomation'
#WorkgroupList = "MultiSite-UserSpan"
#RoleList = "Business User"
LicenseList = "I3_ACCESS_RECORDER"
DepartmentName = "Infr & Ops"
Title = "Process Automation Engineer"
OfficeLocation = "Remote"
AutoAnswerAcdInteractions = $true
}
Update-ICUser #Params
with the output:
processing key 'OfficeLocation'
adding key 'OfficeLocation' with value 'Remote'
processing key 'Title'
processing key 'AutoAnswerAcdInteractions'
adding key 'AutoAnswerAcdInteractions' with value 'True'
value before is 'System.String'
value after is 'System.String'
processing key 'DepartmentName'
processing key 'LicenseList'
LicenseList - casting to array
{
"personalInformationProperties": {
"DepartmentName": "Infr & Ops",
"Title": "Process Automation Engineer"
},
"licenseProperties": {
"additionalLicenses": []
},
"roles": {},
"Workgroups": null,
"OfficeLocation": "Remote",
"AutoAnswerAcdInteractions": true
}

Related

Does a DynamicParameter Switch not read like a Static Parameter [switch]?

Hopefully the Title is clear enough but, I am having some trouble understanding on how to evaluate against a DynamicParameter Switch, compared to a Static (type casted) switch.
In the following code block, there are 2 switches that become available only if the other 2 parameters are not null, and/or, are not empty:
Add
Remove
Function Test-DynamParam {
Param (
# Input Parameters
[Parameter(Mandatory = $false,
HelpMessage='Enter. Workflow. Name.')]
[Alias('OMB','MailBox')]
[string]$Workflow,
[Parameter(Mandatory = $false)]
[Alias('EDIPI','DisplayName')]
[string[]]$UserName
)
DynamicParam {
if ($Workflow -ne $null -and $UserName -ne $null) {
$parameterAttribute = [System.Management.Automation.ParameterAttribute]#{
ParameterSetName = "AddingMembers"
Mandatory = $false
}
$attributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
$attributeCollection.Add($parameterAttribute)
$dynParam1 = [System.Management.Automation.RuntimeDefinedParameter]::new(
'Add', [switch], $attributeCollection
)
$paramDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
$paramDictionary.Add('Add', $dynParam1)
$parameterAttribute1 = [System.Management.Automation.ParameterAttribute]#{
ParameterSetName = "RemovingMembers"
Mandatory = $false
}
$attributeCollection1 = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
$attributeCollection1.Add($parameterAttribute1)
$dynParam11 = [System.Management.Automation.RuntimeDefinedParameter]::new(
'Remove', [switch], $attributeCollection1
)
$paramDictionary.Add('Remove', $dynParam11)
return $paramDictionary
}
}
Process {
$Add.IsPresent
}
}
Running:
Test-DynamParam -Workflow 'd' -UserName 'a' -Add
returns empty.
Unfortunately, $Add.IsPresent is not evaluated to any boolean value regardless if the switch is present or not. Yet in this function it is (which makes sense):
Function Test-StaticParam {
Param (
[switch]$Add
)
$Add.IsPresent
}
Running:
Test-StaticParam -Add
returns True.
Question
How can I evaluate against dynamic parameter chosen?
Use the $PSBoundParameters automatic variable:
Process {
$PSBoundParameters['Add'].IsPresent
}

Custom function, value from pipeline

This a function for changing local user password on a remote machine. I'd like to make it work with a value from pipeline. This works:
$x= #()
$x += Set-UserPassword -ComputerName smz0017d -User localadmin -NewPassword "1"
$x += Set-UserPassword -ComputerName smz0027d -User localadmin -NewPassword "2"
$x | Out-GridView
But with value from pipeline it doesn't. Any tips?
$x = #()
$x += [pscustomobject]#{
ComputerName = 'smzmi0027d'
User = 'localadmin'
NewPassword = 'djkufdjkuf1234'
}
$x += [pscustomobject]#{
ComputerName = 'smzmi0027d'
User = 'localadmin'
NewPassword = '1'
}
foreach ($y in $x)
{
$y | Set-UserPassword
}
The function to accept value from a pipeline. It invokes command on a remote machine and builds custom object with a result:
function Set-UserPasswordLocaly
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true,
Position = 0)]
[string]$User,
[Parameter(Mandatory = $true,
Position = 1)]
[string]$NewPassword
)
#TODO: Place script here
try
{
Set-LocalUser -Name $User -Password (ConvertTo-SecureString $NewPassword -AsPlainText -Force) -ErrorAction Stop
$pwdSetResult = "$user password has been changed"
$isSuccess = $true
}
catch
{
$pwdSetResult = ($_.Exception).Message
$isSuccess = $false
}
return [PSCustomObject]#{
'ComputerName' = $env:COMPUTERNAME
'isSuccess' = $isSuccess
'Message' = $pwdSetResult
}
}
function Set-UserPasswordRemotely
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true,
Position = 0)]
[string]$ComputerName,
[Parameter(Mandatory = $true,
Position = 1)]
[string]$User,
[Parameter(Mandatory = $true,
Position = 2)]
[string]$NewPassword
)
#TODO: Place script here
$param = #{
ComputerName = $ComputerName
ScriptBlock = ${function:Set-UserPasswordLocaly}
ArgumentList = $User, $NewPassword
ErrorAction = 'stop'
}
try
{
$invoke = Invoke-Command #param
$invokeResult = $invoke.Message
$isSuccess = $invoke.isSuccess
}
catch
{
$invokeResult = ($_.Exception).Message
$isSuccess = $false
}
return [PSCustomObject]#{
'ComputerName' = $ComputerName
'isSuccess' = $isSuccess
'Message' = $invokeResult
}
}
function Set-UserPassword
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true,
Position = 0)]
[string]$ComputerName,
[Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true,
Position = 1)]
[string]$User,
[Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true,
Position = 2)]
[string]$NewPassword,
[Parameter(Position = 3,ValueFromPipelineByPropertyName = $true)]
[string]$PasswordVersion
)
#TODO: Place script here
PROCESS
{
if ($env:COMPUTERNAME -eq $ComputerName)
{
Set-UserPasswordLocaly $User $NewPassword
}
else
{
Set-UserPasswordRemotely $ComputerName $User $NewPassword
}
}
}
The ComputerName parameter in Set-UserPassword is not configured to accept pipeline input. Change that and it'll work:
function Set-UserPassword
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true,
Position = 0)]
[string]$ComputerName,
[Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true,
Position = 1)]
[string]$User,
[Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true,
Position = 2)]
[string]$NewPassword,
[Parameter(Position = 3,ValueFromPipelineByPropertyName = $true)]
[string]$PasswordVersion
)
# I'm using Write-Host to demonstrate binding behavior, replace with your actual code
process { Write-Host $PSBoundParameters }
}
PS ~> [pscustomobject]#{
>> ComputerName = 'smzmi0027d'
>> User = 'localadmin'
>> NewPassword = '1'
>> } |Set-UserPassword
>>
[NewPassword, 1] [User, localadmin] [ComputerName, smzmi0027d]

Edited post, but still listed as duplicate [duplicate]

I have two functions one creates a custom object which once done is piped to the next function. The problem is that the second function is not receiving my object correctly. Instead of using the pipeline I have tried setting a variable and then piping that variable to the function. Below are the two functions with the output of get member on the returned object. All the string param are being processed correctly. But the objects simply wont work. In the begin block of the New-BaseGuest I am not able to assign the results to the variables.
Basically I want to end up with:
Get-ServerFromXML -XMLFile File -GuestName Name | New-BaseGuest
The New-BaseGuest function is incomplete as I cannot get the parameters working.
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
CDROM_Connected NoteProperty object CDROM_Connected=null
CDROM_ISO NoteProperty object CDROM_ISO=null
Floppy_Connected NoteProperty object Floppy_Connected=null
Floppy_ISO NoteProperty object Floppy_ISO=null
GuestType NoteProperty string GuestType=vmkernel6Guest
IPAddress NoteProperty string IPAddress=192.168.199.40
ServerName NoteProperty string ServerName=ESX-VSAN3
vCPU NoteProperty string vCPU=2
vHDD NoteProperty Object[] vHDD=System.Object[]
vNIC NoteProperty Object[] vNIC=System.Object[]
vRAM NoteProperty string vRAM=5120
function Get-ServerFromXML
{
<##>
[CmdletBinding()]
param
(
[String]
$XMLFile,
[String]
$GuestName
)
$xml = New-Object -TypeName XML
$xml.Load($XMLFile)
$Server = Select-Xml -Xml $xml -XPath ('/Servers/Server[#Name = "' + $GuestName + '" ]')
$vNicObjs = #()
$vHddobjs = #()
If ($Server.Node.Hardware.vnic.Count -ne $null)
{
$Server.Node.Hardware.vnic | %{
$NicProps = #{
NIC_ID = $_.ID;
NIC_Type = $_.Type;
NIC_StartConnected = $_.StartConnected;
NIC_MACAddress = $_.MACAddress;
NIC_WakeOnLan = $_.WakeOnLan;
NIC_PortGroup = $_.PortGroup
}
$vNicObj = New-Object -TypeName System.Management.Automation.PSObject -Property $NicProps
$vNicObjs += $vNicObj
}
}
Else
{
$NicProps = #{
NIC_ID = $Server.Node.Hardware.vnic.ID;
NIC_Type = $Server.Node.Hardware.vnic.Type;
NIC_StartConnected = $Server.Node.Hardware.vnic.StartConnected;
NIC_MACAddress = $Server.Node.Hardware.vnic.MACAddress;
NIC_WakeOnLan = $Server.Node.Hardware.vnic.WakeOnLan;
NIC_PortGroup = $Server.Node.Hardware.vnic.PortGroup
}
$vNivObj = New-Object -TypeName System.Management.Automation.PSObject -Property $NicProps
$vNicObjs += $vNivObj
}
If ($Server.Node.Hardware.vHDD.Count -ne $null)
{
$Server.Node.Hardware.vHDD | %{
$HDDProps = #{
HDD_ID = $_.ID;
HDD_Type = $_.Type;
HDD_Size = $Server.Node.Hardware.vHDD.Size;
HDD_Datastore = $_.Datastore;
HDD_StorageFormate = $_.StorageFormat
}
$vHDDObj = New-Object -TypeName System.Management.Automation.PSObject -Property $HDDProps
$vHDDObjs += $vHDDObj
}
}
Else
{
$HDDProps = #{
HDD_ID = $Server.Node.Hardware.vHDD.ID;
HDD_Type = $Server.Node.Hardware.vHDD.Type;
HDD_Size = $Server.Node.Hardware.vHDD.Size;
HDD_DataStore = $Server.Node.Hardware.vHDD.Datastore;
HDD_StorageFormat = $Server.Node.Hardware.vHDD.StorageFormat
}
$vHDDObj = New-Object -TypeName System.Management.Automation.PSObject -Property $HDDProps
$vHDDObjs += $vHDDObj
}
$ServerProps =[Ordered]#{
ServerName = $Server.Node.Description.Name;
GuestType = $Server.Node.Description.GuestType;
IPAddress = $Server.Node.Description.PrimaryIP;
vCPU = $Server.Node.Hardware.vCPU;
vRAM = $Server.Node.Hardware.vRAM;
vHDD = $vHddobjs;
vNIC = $vNicObjs;
CDROM_ISO = $Server.Node.Hardware.CDROM.ISOPath
CDROM_Connected = $Server.Node.Hardware.CDROM.StartConnected
Floppy_ISO = $Server.Node.Hardware.Floppy.ISOPath
Floppy_Connected = $Server.Node.Hardware.Floppy.StartConnected
}
$ServerObj = New-Object -TypeName System.Management.Automation.PSObject -Property $ServerProps
$ServerObj
}
function New-BaseGuest
{
<##>
[CmdletBinding(PositionalBinding = $true,
SupportsShouldProcess = $true)]
param
(
[Parameter(Mandatory = $true,
ValueFromPipeline = $false,
ValueFromPipelineByPropertyName = $true,
Position = 1)]
[string]
$ServerName,
[Parameter(Mandatory = $true,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
Position = 2)]
[string]
$GuestType,
[Parameter(Mandatory = $true,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
Position = 3)]
[string]
$vCPU,
[Parameter(Mandatory = $true,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
Position = 4)]
[string]
$vRAM,
[Parameter(Mandatory = $true,
ValueFromPipelineByPropertyName = $true,
Position = 5)]
[system.object]
$vHDD,
[Parameter(Mandatory = $true,
ValueFromPipelineByPropertyName = $true,
Position = 6)]
[system.object]
$vNIC,
[Parameter(Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
Position = 7)]
[string]
$CDROM_ISO = $Null,
[Parameter(Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
Position = 8)]
[string]
$FLOPPY_ISO = $Null,
[Parameter(Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
Position = 9)]
[string]
$CDROM_Connected = $Null,
[Parameter(Mandatory = $true,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
Position = 10)]
[string]
$Floppy_Connected = $Null
)
BEGIN
{
$Datastore = ($vHDD | Where-Object { $_.HDD_ID -eq 1 } | Select-Object -Property HDD_DataStore).HDD_DataStore
$PortGroup = ($vNIC | Where-Object { $_.NIC_ID -eq 1 } | Select-Object -Property NIC_PortGroup).NIC_PortGroup
$DiskSize = ($vHDD | Where-Object { $_.HDD_ID -eq 1 } | Select-Object -Property HDD_Size).HDD_Size
$DiskFormat = ($vHDD | Where-Object { $_.HDD_ID -eq 1 } | Select-Object -Property HDD_StorageFormat).HDD_StorageFormat
}
PROCESS
{
New-VM -Name $ServerName `
-Datastore $Datastore `
-NumCPU $vCPU `
-MemoryGB $vRAM`
-DiskGB $DiskSize `
-NetworkName $PortGroup `
-DiskStorageFormat $CDROM_ISO `
-GuestID $GuestType | Out-Null
}
END
{
}
}
This is expected behavior. The begin {} block runs before any pipeline objects are encountered, so you have no access to any parameters that come in through the pipeline in your begin block.
The process {} block is run once for each item, so the code you have in the begin block really needs to be put there (because it's specific to a single VM).

Powershell Object not being piped through to Functions

I have two functions one creates a custom object which once done is piped to the next function. The problem is that the second function is not receiving my object correctly. Instead of using the pipeline I have tried setting a variable and then piping that variable to the function. Below are the two functions with the output of get member on the returned object. All the string param are being processed correctly. But the objects simply wont work. In the begin block of the New-BaseGuest I am not able to assign the results to the variables.
Basically I want to end up with:
Get-ServerFromXML -XMLFile File -GuestName Name | New-BaseGuest
The New-BaseGuest function is incomplete as I cannot get the parameters working.
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
CDROM_Connected NoteProperty object CDROM_Connected=null
CDROM_ISO NoteProperty object CDROM_ISO=null
Floppy_Connected NoteProperty object Floppy_Connected=null
Floppy_ISO NoteProperty object Floppy_ISO=null
GuestType NoteProperty string GuestType=vmkernel6Guest
IPAddress NoteProperty string IPAddress=192.168.199.40
ServerName NoteProperty string ServerName=ESX-VSAN3
vCPU NoteProperty string vCPU=2
vHDD NoteProperty Object[] vHDD=System.Object[]
vNIC NoteProperty Object[] vNIC=System.Object[]
vRAM NoteProperty string vRAM=5120
function Get-ServerFromXML
{
<##>
[CmdletBinding()]
param
(
[String]
$XMLFile,
[String]
$GuestName
)
$xml = New-Object -TypeName XML
$xml.Load($XMLFile)
$Server = Select-Xml -Xml $xml -XPath ('/Servers/Server[#Name = "' + $GuestName + '" ]')
$vNicObjs = #()
$vHddobjs = #()
If ($Server.Node.Hardware.vnic.Count -ne $null)
{
$Server.Node.Hardware.vnic | %{
$NicProps = #{
NIC_ID = $_.ID;
NIC_Type = $_.Type;
NIC_StartConnected = $_.StartConnected;
NIC_MACAddress = $_.MACAddress;
NIC_WakeOnLan = $_.WakeOnLan;
NIC_PortGroup = $_.PortGroup
}
$vNicObj = New-Object -TypeName System.Management.Automation.PSObject -Property $NicProps
$vNicObjs += $vNicObj
}
}
Else
{
$NicProps = #{
NIC_ID = $Server.Node.Hardware.vnic.ID;
NIC_Type = $Server.Node.Hardware.vnic.Type;
NIC_StartConnected = $Server.Node.Hardware.vnic.StartConnected;
NIC_MACAddress = $Server.Node.Hardware.vnic.MACAddress;
NIC_WakeOnLan = $Server.Node.Hardware.vnic.WakeOnLan;
NIC_PortGroup = $Server.Node.Hardware.vnic.PortGroup
}
$vNivObj = New-Object -TypeName System.Management.Automation.PSObject -Property $NicProps
$vNicObjs += $vNivObj
}
If ($Server.Node.Hardware.vHDD.Count -ne $null)
{
$Server.Node.Hardware.vHDD | %{
$HDDProps = #{
HDD_ID = $_.ID;
HDD_Type = $_.Type;
HDD_Size = $Server.Node.Hardware.vHDD.Size;
HDD_Datastore = $_.Datastore;
HDD_StorageFormate = $_.StorageFormat
}
$vHDDObj = New-Object -TypeName System.Management.Automation.PSObject -Property $HDDProps
$vHDDObjs += $vHDDObj
}
}
Else
{
$HDDProps = #{
HDD_ID = $Server.Node.Hardware.vHDD.ID;
HDD_Type = $Server.Node.Hardware.vHDD.Type;
HDD_Size = $Server.Node.Hardware.vHDD.Size;
HDD_DataStore = $Server.Node.Hardware.vHDD.Datastore;
HDD_StorageFormat = $Server.Node.Hardware.vHDD.StorageFormat
}
$vHDDObj = New-Object -TypeName System.Management.Automation.PSObject -Property $HDDProps
$vHDDObjs += $vHDDObj
}
$ServerProps =[Ordered]#{
ServerName = $Server.Node.Description.Name;
GuestType = $Server.Node.Description.GuestType;
IPAddress = $Server.Node.Description.PrimaryIP;
vCPU = $Server.Node.Hardware.vCPU;
vRAM = $Server.Node.Hardware.vRAM;
vHDD = $vHddobjs;
vNIC = $vNicObjs;
CDROM_ISO = $Server.Node.Hardware.CDROM.ISOPath
CDROM_Connected = $Server.Node.Hardware.CDROM.StartConnected
Floppy_ISO = $Server.Node.Hardware.Floppy.ISOPath
Floppy_Connected = $Server.Node.Hardware.Floppy.StartConnected
}
$ServerObj = New-Object -TypeName System.Management.Automation.PSObject -Property $ServerProps
$ServerObj
}
function New-BaseGuest
{
<##>
[CmdletBinding(PositionalBinding = $true,
SupportsShouldProcess = $true)]
param
(
[Parameter(Mandatory = $true,
ValueFromPipeline = $false,
ValueFromPipelineByPropertyName = $true,
Position = 1)]
[string]
$ServerName,
[Parameter(Mandatory = $true,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
Position = 2)]
[string]
$GuestType,
[Parameter(Mandatory = $true,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
Position = 3)]
[string]
$vCPU,
[Parameter(Mandatory = $true,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
Position = 4)]
[string]
$vRAM,
[Parameter(Mandatory = $true,
ValueFromPipelineByPropertyName = $true,
Position = 5)]
[system.object]
$vHDD,
[Parameter(Mandatory = $true,
ValueFromPipelineByPropertyName = $true,
Position = 6)]
[system.object]
$vNIC,
[Parameter(Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
Position = 7)]
[string]
$CDROM_ISO = $Null,
[Parameter(Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
Position = 8)]
[string]
$FLOPPY_ISO = $Null,
[Parameter(Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
Position = 9)]
[string]
$CDROM_Connected = $Null,
[Parameter(Mandatory = $true,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
Position = 10)]
[string]
$Floppy_Connected = $Null
)
BEGIN
{
$Datastore = ($vHDD | Where-Object { $_.HDD_ID -eq 1 } | Select-Object -Property HDD_DataStore).HDD_DataStore
$PortGroup = ($vNIC | Where-Object { $_.NIC_ID -eq 1 } | Select-Object -Property NIC_PortGroup).NIC_PortGroup
$DiskSize = ($vHDD | Where-Object { $_.HDD_ID -eq 1 } | Select-Object -Property HDD_Size).HDD_Size
$DiskFormat = ($vHDD | Where-Object { $_.HDD_ID -eq 1 } | Select-Object -Property HDD_StorageFormat).HDD_StorageFormat
}
PROCESS
{
New-VM -Name $ServerName `
-Datastore $Datastore `
-NumCPU $vCPU `
-MemoryGB $vRAM`
-DiskGB $DiskSize `
-NetworkName $PortGroup `
-DiskStorageFormat $CDROM_ISO `
-GuestID $GuestType | Out-Null
}
END
{
}
}
This is expected behavior. The begin {} block runs before any pipeline objects are encountered, so you have no access to any parameters that come in through the pipeline in your begin block.
The process {} block is run once for each item, so the code you have in the begin block really needs to be put there (because it's specific to a single VM).

Can I make a parameter set depend on the value of another parameter?

Let's say I have a function like:
function Authenticate
{
param
(
[ValidateSet('WindowsAuthentication','UsernameAndPassword')][string] $AuthenticationType,
[Parameter(ParameterSetName='Set1')][string] $Username,
[Parameter(ParameterSetName='Set1')][string] $Password
)
..
}
And I would like to make the parameter set to be mandatory when $AuthenticationType = 'UsernameAndPassword' but also so that it cannot be used if $AuthenticationType = 'WindowsAuthentication'.
It this even possible in PowerShell?
Using the link from Tim Ferrill's answer, I created the following function to help create dynamic parameters:
function New-DynamicParameter
{
[CmdletBinding(DefaultParameterSetName = 'Core')]
param
(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)][string] $Name,
[Parameter(Mandatory = $true, ParameterSetName = 'Core')][Parameter(Mandatory = $true, ParameterSetName = 'ValidateSet')][type] $Type,
[Parameter(Mandatory = $false)][string] $ParameterSetName = '__AllParameterSets',
[Parameter(Mandatory = $false)][bool] $Mandatory = $false,
[Parameter(Mandatory = $false)][int] $Position,
[Parameter(Mandatory = $false)][bool] $ValueFromPipelineByPropertyName = $false,
[Parameter(Mandatory = $false)][string] $HelpMessage,
[Parameter(Mandatory = $true, ParameterSetName = 'ValidateSet')][string[]] $ValidateSet,
[Parameter(Mandatory = $false, ParameterSetName = 'ValidateSet')][bool] $IgnoreCase = $true
)
process
{
# Define Parameter Attributes
$ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute
$ParameterAttribute.ParameterSetName = $ParameterSetName
$ParameterAttribute.Mandatory = $Mandatory
$ParameterAttribute.Position = $Position
$ParameterAttribute.ValueFromPipelineByPropertyName = $ValueFromPipelineByPropertyName
$ParameterAttribute.HelpMessage = $HelpMessage
# Define Parameter Validation Options if ValidateSet set was used
if ($PSCmdlet.ParameterSetName -eq 'ValidateSet')
{
$ParameterValidateSet = New-Object System.Management.Automation.ValidateSetAttribute -ArgumentList $ValidateSet -Strict (!$IgnoreCase)
}
# Add Parameter Attributes and ValidateSet to an Attribute Collection
$AttributeCollection = New-Object Collections.ObjectModel.Collection[System.Attribute]
$AttributeCollection.Add($ParameterAttribute)
$AttributeCollection.Add($ParameterValidateSet)
# Add parameter to parameter list
$Parameter = New-Object System.Management.Automation.RuntimeDefinedParameter -ArgumentList #($Name, $Type, $AttributeCollection)
# Expose parameter to the namespace
$ParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
$ParameterDictionary.Add($Name, $Parameter)
return $ParameterDictionary
}
}
And solved my particular problem in the following way:
function Authenticate
{
param
(
[ValidateSet('WindowsAuthentication','UsernameAndPassword')][string] $AuthenticationType,
)
DynamicParam
{
if ($AuthenticationType -eq 'UsernameAndPassword')
{
New-DynamicParameter Username [string] -Mandatory $true
New-DynamicParameter Password [string] -Mandatory $true
}
}
...
}
It became unneeded to have a parameter set when using Dynamic Parameter so I removed the parameter set.
You can do this using DynamicParam. I saw a decent post on this recently here.
DynamicParam {
if ($AuthenticationType -eq 'UsernameAndPassword') {
#create ParameterAttribute Objects for the username and password
$unAttribute = New-Object System.Management.Automation.ParameterAttribute
$unAttribute.Mandatory = $true
$unAttribute.HelpMessage = "Please enter your username:"
$pwAttribute = New-Object System.Management.Automation.ParameterAttribute
$pwAttribute.Mandatory = $true
$pwAttribute.HelpMessage = "Please enter a password:"
#create an attributecollection object for the attributes we just created.
$attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
#add our custom attributes
$attributeCollection.Add($unAttribute)
$attributeCollection.Add($pwAttribute)
#add our paramater specifying the attribute collection
$unParam = New-Object System.Management.Automation.RuntimeDefinedParameter('username', [string], $attributeCollection)
$pwParam = New-Object System.Management.Automation.RuntimeDefinedParameter('password', [string], $attributeCollection)
#expose the name of our parameter
$paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
$paramDictionary.Add('username', $unParam)
$paramDictionary.Add('password', $pwParam)
return $paramDictionary
}
}
Process {
$PSBoundParameters.username
$PSBoundParameters.password
}