Cmdlet Using Advanced Parameter Sets in a Function with Multiple Unique Switches

I am using Powershell 4.0.

I am attempting to write a cmdlet and in this cmdlet I would like to use Advanced Parameter sets to have certain options available based on what parameter(s) is/are chosen. This particular function will essentially and eventually be Get-ADComputer but with the -SearchBase preprogrammed for certain options.

I have 6 parameters total. 2 are strings ($ComputerName or $IpAddress), 1 is an integer ($OULevel) and 3 switches ($ComputerOU, $AllCompany, $List).

I have a parameter set each for ComputerName and IPAddress, I would like the user to be able to input one or the other - I think I have this figured out its pretty simple. However, I would like $OULevel, $ComputerOU and $AllCompany to be exclusive meaning if one is used the other should not be able to be used. $List should remain available in each scenario.

I have tried different variations of the parameter sets to no avail. This is what my script looks like now, with some trimmed back:

    function Get-CompanyADComputer{
         [CmdletBinding(DefaultParametersetName="ComputerName")]

    Param(
        [Parameter(Mandatory=$true,
                    ParameterSetName="ComputerName",
                    Position=0,
                    ValueFromPipeline=$false,
                    HelpMessage='Enter a computer name to search in ActiveDirectory.')]
        [Alias('Computer','CN')]
        [string]$ComputerName,

        [Parameter(Mandatory=$true,
                    ParameterSetName="IPAddress",
                    Position=0,
                    ValueFromPipeline=$false,
                    HelpMessage='Enter an IP address to search in ActiveDirectory.')]
        [Alias('IPv4Address','IPv6Address')]
        [string]$IPAddress,

        [Parameter(Mandatory=$false,
                    HelpMessage='Enter a number between 0 and 8. 0 is your current OU Container.')]
        [ValidateRange(0,8)]
        [int]$OULevel = 0,

        [Parameter()]
        [Switch]$ComputerOU,

        [Parameter()]
        [Switch]$AllCompany,

        [Parameter()]
        [Switch]$List
    )

If you are curious our AD is organized by Location, then category (computer, user, groups, contacts, etc) and then it gets more granular in each OU below. This script detects your computer’s OU and starts the search there. The purpose of $OULevel is if the user specifies a different number the search will start in a different OU and then search recursively. The purpose of $ComputerOU is to have your search go to the default Computers OU instead of the entire domain or your location. The purpose of $AllCompany is to have the search default to the entire domain instead of any other choice or OU.

Any guidance is appreciated. I can’t seem to get the hang of this one without my script getting all convoluted.

So, you can potentially go with dynamic parameters, but I’m not sure that’s the right thing.

If I’m understanding the question, then you basically have to factor out all the possible combinations. Remember that a param can belong to 1+ param sets. So, you might have a set with Computername and OULevel, Computername and ComputerOU, and Computername and AllCompany. That’s three. Then those three again for IPAddress. I know it’s not elegant, but look at the help for Where-Object - not elegant, either, by far. List would then not belong to a set, which means it would belong to all.

Thanks Don! I ended up simplifying my script so I need one less parameter but I’ll include the solution that would have been if I had kept my cmdlet exactly the same. Hopefully this will benefit someone else.

    function Get-CompanyADComputer{
     [CmdletBinding(DefaultParametersetName="ComputerName")]

Param(
    [Parameter(Mandatory=$true,
                ParameterSetName="ComputerName",
                Position=0,
                ValueFromPipeline=$false,
                HelpMessage='Enter a computer name to search in ActiveDirectory.')]
    [Parameter(Mandatory=$true,
                ParameterSetName="ComputerNameOULevel",
                Position=0,
                ValueFromPipeline=$false,
                HelpMessage='Enter a computer name to search in ActiveDirectory.')]
    [Parameter(Mandatory=$true,
                ParameterSetName="ComputerNameComputerOU",
                Position=0,
                ValueFromPipeline=$false,
                HelpMessage='Enter a computer name to search in ActiveDirectory.')]
    [Parameter(Mandatory=$true,
                ParameterSetName="ComputerNameAllCompany",
                Position=0,
                ValueFromPipeline=$false,
                HelpMessage='Enter a computer name to search in ActiveDirectory.')]
    [Alias('Computer','CN')]
    [string]$ComputerName,

    [Parameter(Mandatory=$true,
                ParameterSetName="IPAddress",
                Position=0,
                ValueFromPipeline=$false,
                HelpMessage='Enter an IP address to search in ActiveDirectory.')]
    [Parameter(Mandatory=$true,
                ParameterSetName="IPAddressOULevel",
                Position=0,
                ValueFromPipeline=$false,
                HelpMessage='Enter an IP address to search in ActiveDirectory.')]
    [Parameter(Mandatory=$true,
                ParameterSetName="IPAddressComputerOU",
                Position=0,
                ValueFromPipeline=$false,
                HelpMessage='Enter an IP address to search in ActiveDirectory.')]
    [Parameter(Mandatory=$true,
                ParameterSetName="IPAddressAllCompany",
                Position=0,
                ValueFromPipeline=$false,
                HelpMessage='Enter an IP address to search in ActiveDirectory.')]
    [Alias('IPv4Address','IPv6Address')]
    [string]$IPAddress,

    [Parameter(Mandatory=$false,
                ParameterSetName="ComputerNameOULevel",
                HelpMessage='Enter a number between 0 and 8. 0 is your current OU Container.')]
    [Parameter(Mandatory=$false,
                ParameterSetName="IPAddressOULevel",
                HelpMessage='Enter a number between 0 and 8. 0 is your current OU Container.')]
    [ValidateRange(0,8)]
    [int]$OULevel = 0,

    [Parameter(ParameterSetName="ComputerNameComputerOU")]
    [Parameter(ParameterSetName="IPAddressComputerOU")]
    [Switch]$ComputerOU,

    [Parameter(ParameterSetName="ComputerNameAllCompany")]
    [Parameter(ParameterSetName="IPAddressAllCompany")]
    [Switch]$AllCompany,

    [Parameter()]
    [Switch]$List
)

do you strictly need to differentiate computer name from ip address ?
And even it is need it can be simpified by script
something like this

param([string]$Computername)
try {
 $IP=[System.Net.IPAddress]::Parse($ComputerName)
'this can be parsed as ip address, it is ip address'
$ip
 }
catch {
'This is string, assume it is computer name'
}

Thanks for the information. Yes in this case I do have to specify one over the other because this cmdlet essentially is just a shell for Get-ADComputer or Get-ADUser with some of its parameters pre-configured for the company I work with. Get-ADComputer is pretty picky if you use IPAddress over ComputerName so that is the need for different parameters on my custom cmdlet.

Thank you for the info though.

Even if you get ip and can’t use it directly with (Get-ADComputer), you always can resolve it with
[Net.Dns]::Resolve()
btw, it even better than my previous suggestion, because it can resolve any of computername or ipaddress to hostname (but you can get problems with cluster or other one-to-many resolvable objects)

The following script is failing due to the named parameter sets…
Test-Params : Parameter set cannot be resolved using the specified named parameters.

Function Test-Params
{
    [CmdletBinding()]
	Param(
        [Parameter(Mandatory=$true)]
        [string]$ValueKey,

        [Parameter(Mandatory=$true, ParameterSetName="ComputerNameAttemptOnline")]
        [Parameter(Mandatory=$true, ParameterSetName="ComputerNameLookupOrder")]
        [switch]$SearchByComputerName,

        [Parameter(Mandatory=$false, ParameterSetName="ComputerNameAttemptOnline")]
        [Parameter(Mandatory=$false, ParameterSetName="ComputerNameLookupOrder")]
        [string]$ComputerName=$env:ComputerName,

        [Parameter(Mandatory=$true, ParameterSetName="SearchByOUAttemptOnline")]
        [Parameter(Mandatory=$true, ParameterSetName="SearchByOULookupOrder")]
        [switch]$SearchByOU,

        [Parameter(Mandatory=$false, ParameterSetName="SearchByOUAttemptOnline")]
        [Parameter(Mandatory=$false, ParameterSetName="SearchByOULookupOrder")]
        [string]$MachineOU,

        [Parameter(Mandatory=$false)]
        [ValidateNotNullOrEmpty()]
        [string]$DefaultValue,

        [Parameter(Mandatory=$false)]
        [ValidateNotNullOrEmpty()]
        [string]$OfflineSettingsFile="$scriptParentPath\OfflineSettings.ini",

        [Parameter(Mandatory=$false, ParameterSetName="ComputerNameAttemptOnline")]
        [Parameter(Mandatory=$false, ParameterSetName="SearchByOUAttemptOnline")]
        [switch]$AttemptOfflineModeFirst,

        [Parameter(Mandatory=$false, ParameterSetName="ComputerNameLookupOrder")]
        [Parameter(Mandatory=$false, ParameterSetName="SearchByOULookupOrder")]
        [string[]]$LookupOrder=@("Server", "Local"),

        [Parameter(Mandatory=$false)]
        [switch]$Decrypt
    )

        "ParameterSetName: $($PSCmdlet.ParameterSetName)"
}

However, Get-Help indicates that it should work …

Test-Params -<strong>ValueKey</strong>  -<strong>SearchBy<strong>ComputerName</strong></strong>  [-<strong>ComputerName</strong> ] [-<strong>DefaultValue</strong> ] [-<strong>OfflineSettingsFile</strong> ] [-<strong>LookupOrder</strong> ] [-<strong>Decrypt</strong> ] []

Test-Params -<strong>ValueKey</strong>  -<strong>SearchBy<strong>ComputerName</strong></strong>  [-<strong>ComputerName</strong> ] [-<strong>DefaultValue</strong> ] [-<strong>OfflineSettingsFile</strong> ] [-<strong>AttemptOfflineModeFirst</strong> ] [-<strong>Decrypt</strong> ] []

Test-Params -<strong>ValueKey</strong>  -<strong>SearchByOU</strong>  [-<strong>MachineOU</strong> ] [-<strong>DefaultValue</strong> ] [-<strong>OfflineSettingsFile</strong> ] [-<strong>LookupOrder</strong> ] [-<strong>Decrypt</strong> ] []

Test-Params -<strong>ValueKey</strong>  -<strong>SearchByOU</strong>  [-<strong>MachineOU</strong> ] [-<strong>DefaultValue</strong> ] [-<strong>OfflineSettingsFile</strong> ] [-<strong>AttemptOfflineModeFirst</strong> ] [-<strong>Decrypt</strong> ] []

Thanks in advance for your assistance

you listing indicate only that Test-Params have several parameter sets and it doesn’t have default parameter set

until you list the command you use to invoke Test-Params function noone can help you