Search code examples
c#.netpowershellcommandlet

C# Powershell Commandlet to work with two parameters, but at most one can be specified


I am implementing a Powershell commandlet in C#. The commandlet can be passed two parameters. Both are marked as optional (because I don't know in advance whether the user will issue Get-MsiInstalled -Product "0449F3E3-2337-45EF-BE77-60F4B9CD8822" Or Get-MsiInstalled -MsiFile "C:filePath\file.msi".

Moreover, if the user is giving nothing and issueing Get-MsiInstalled an exception will be thrown (Either MSI or Product parameter must be specified).

Right now the implementation can't expect at most one parameter. Instead the user can provide both parameters and that is an invalid call.

public class GetAHPIsMsiInstalled : Cmdlet
{      
    [Parameter(Mandatory = false, ValueFromPipeline = true,
        HelpMessage = "Product Guid to search Installable Package.", Position = 1)]
    [UsedImplicitly]
    public string Product { get; set; }

    [Parameter(Mandatory = false, ValueFromPipeline = true, HelpMessage = "Installable Package to search.",
        Position = 1)]
    [UsedImplicitly]
    public string MsiFile { get; set; }

    protected override void BeginProcessing()
    {
        if (string.IsNullOrEmpty(Product) && string.IsNullOrEmpty(MsiFile))
            ThrowTerminatingError(new ErrorRecord(new
                    ParameterBindingException("At most one parameter must be provided"))

        base.BeginProcessing();
        ................................
     }
}

Solution

  • ParameterSets are the way to specify mutually-exclusive sets of parameters.

    This is how, for example, Get-Process can be called with -Name or -Id, but not both:

    Get-Process [[-Name] <String[]>] [-ComputerName <String[]>] [-FileVersionInfo] [-Module] [<CommonParameters>]
    
    Get-Process [-ComputerName <String[]>] [-FileVersionInfo] -Id <Int32[]> [-Module] [<CommonParameters>]
    
    Get-Process [-ComputerName <String[]>] [-FileVersionInfo] -InputObject <Process[]> [-Module] [<CommonParameters>]
    
    Get-Process -Id <Int32[]> -IncludeUserName [<CommonParameters>]
    
    Get-Process [[-Name] <String[]>] -IncludeUserName [<CommonParameters>]
    
    Get-Process -IncludeUserName -InputObject <Process[]> [<CommonParameters>]
    

    You can specify them in C# or directly in PowerShell