Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 173
  • Last Modified:

Why is this messing up my parameter set?

I hate to ask yet another question involving Powershell parametersets but I can't figure out why something is breaking my code. Take a look at this code:

[CmdletBinding(SupportsShouldProcess=$TRUE)]
Param(
    [parameter(ValueFromPipeline=$TRUE)]
    $ComputerName=[System.Net.Dns]::GetHostName(),
    $group="Administrators",
  [parameter(Mandatory=$true,ParameterSetName="add")]
    [System.Security.SecureString] $Password,
    [parameter(Mandatory=$true,ParameterSetName="add")]
     $add,
  [parameter(Mandatory=$true,ParameterSetName="delete")]
  [Parameter(ParameterSetName="add")]
   $delete
)

Write-Output "Delete: $Delete"
Write-Output "Add: $Add"

This is a shorter piece of code to help figure out the problem with a much longer powershell script. Anyway the code works IF I don't pass anything in the pipeline just to the "delete" parameter. So the following all work:

.\TestExchange.ps1 -add testUser
.\TestExchange.ps1 -delete testUser
Get-Content .\ComputerList.txt | .\TestExchange.ps1 -add testUser
Get-Content .\ComputerList.txt | .\TestExchange.ps1 -add testUser -delete testUser2

However the following causes a problem:

Get-Content .\ComputerList.txt | .\TestExchange.ps1 -delete testUser

When I do this I am inexplicably prompted for both the "password" parameter and the "add" parameter.  When I simply pass the "delete" parameter I should NOT be prompted for the "password" and "add" parameters (the "password" parameter should only prompt if I pass the "Add" parameter).  "ComputerList.txt" simply contains a string of a single computer BTW.

Can anyone explain why this is happening? I don't understand why passing the "delete" parameter works by itself, but if I use the pipeline in front of it it suddenly thinks I want to use the "add" parameterset instead of the "delete" parameterset.

Any help is much appreciated.
0
rsts_support
Asked:
rsts_support
2 Solutions
 
DansDadUKCommented:
I know very little about Powershell, but it seems that your definition does not satisfy the rule that "Each parameter set must have at least one unique parameter. If possible, make this parameter a mandatory parameter".

i.e. parameter set 'add' has parameters:
computername (mandatory?)
password (mandatory)
$add (mandatory)
$delete (optional)

and parameter set 'delete' has parameters:
computername (mandatory?)
$delete (mandatory)
0
 
SubsunCommented:
Here you have defined the Delete parameter under the ParameterSetName 'add'

[parameter(Mandatory=$true,ParameterSetName="delete")]
 [Parameter(ParameterSetName="add")]
  $delete


Try to remove [Parameter(ParameterSetName="add")]

[parameter(Mandatory=$true,ParameterSetName="delete")]
$delete
0
 
DansDadUKCommented:
Try to remove ...

Which will mean that the two parameter sets then each have at least one unique parameter.
0
 
footechCommented:
I know from your previous question that one of your goals is to require that at least one at least one of the parameters (-add or -delete) be specified.

What seems to be happening is that when processing the pipeline input, it is determining that the matching parameter set is "add".  I can't say why exactly this is.

You may be coming up against some limitations with what you can do with parameter restrictions.  You may be better off doing some checks on variables at the start of the script to handle the various combinations.

However, one solution that seems to work is to follow the guidance which DansDadUK posted, which is to make sure that you have at least one unique parameter for each set.  For example:
[CmdletBinding(SupportsShouldProcess=$TRUE)]
 Param(
     [parameter(ValueFromPipeline=$TRUE)]
     $ComputerName=[System.Net.Dns]::GetHostName(),
     $group="Administrators",
   [parameter(Mandatory=$true,ParameterSetName="add")]
     [System.Security.SecureString] $Password,
     [parameter(Mandatory=$true,ParameterSetName="add")]
      $add,
   [parameter(Mandatory=$true,ParameterSetName="delete")]
   [Parameter(ParameterSetName="add")]
    $delete,
    [parameter(Mandatory=$true,ParameterSetName="delete")]
    [switch]$confirmd
 )

 Write-Output "Delete: $Delete"
 Write-Output "Add: $Add"

Open in new window

When you want to use the -delete parameter without the -add parameter, you need to specify the -confirmd parameter.

In some scenarios, specify a default parameter set can also work.
[CmdletBinding(SupportsShouldProcess=$TRUE, DefaultParameterSetName = "delete")]

Open in new window

0
 
rsts_supportAuthor Commented:
Thanks guys. I will use a default parameter set for now (or possibly adding an optional parameter to "Delete" that essentially will not be used but will give the parameters set a unique parameter).

I must say that Powershell parameter's are at the very least very awkward to use.  If I run into any other issues with them I will probably just chuck the lot and resort to variables with if/then statements. Thanks for your help.
0

Featured Post

 The Evil-ution of Network Security Threats

What are the hacks that forever changed the security industry? To answer that question, we created an exciting new eBook that takes you on a trip through hacking history. It explores the top hacks from the 80s to 2010s, why they mattered, and how the security industry responded.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now