powershellparameter-sets

How do you change a parameter's throw message?


Question: Looking to either change the error message displayed to say they need the '-passed, -warning, or -failed' to be included with the cmdlet parameters or to not care if the three are missing and to write the message (assuming its there).

Explanation: Created a function that takes in three arguments: a message, 2nd message, and state of message (pass, fail, warn). I get a default error message of "Parameter cannot be resolved using the specified named parameters." This happens regardless of if you're passing a message through:

PS C:\> Write-Message;
Write-Message : Parameter set cannot be resolved using the specified named parameters.
...
//or
PS C:\> Write-Message -Message "Hello World";

But if you were to enter in the 'status' parameter it would work without any issues:

PS C:\> Write-Message -Message "Hello World" -Passed;
Hello World 

('Hello World' is supposed to be the color Green here, but Stack Overflow doesn't have that feature yet)

Function in question:

Function Write-Message {
    param(
        [string]$Message,
        [string]$MessageTwo,
        [Parameter(Mandatory=$false, ValueFromPipelineByPropertyName = $true, ParameterSetName ="Passed")][switch]$Passed,
        [Parameter(Mandatory=$false, ValueFromPipelineByPropertyName = $true, ParameterSetName ="Warning")][switch]$Warning,
        [Parameter(Mandatory=$false, ValueFromPipelineByPropertyName = $true, ParameterSetName ="Failed")][switch]$Failed
    );
    $NewLineNeeded = [string]::IsNullOrEmpty($MessageTwo);

    if ($Passed){
        $color = 'green';
    }
    if($Warning){
        $color = 'yellow';
    }
    if($Failed){
        $color = 'red';
    }

    if($Passed -or $Warning -or $Failed){
        if(!$NewLineNeeded){
            Write-Host $MessageOne -NoNewline;
            Write-Host $MessageTwo -ForegroundColor $color;
        } else {
            Write-Host $Message -ForegroundColor $color;
        }  
    }
}

Solution

  • Add a "default" parameter set to resolve this. You don't actually have to use the parameter set in your code, so even using something like "Default" would work without additional changes to your code. I've run into this myself when writing more complex cmdlets where I use parameter sets for mutually exclusive parameters, but some parameters are parameter-set agnostic.

    Function Write-Message {
      [CmdletBinding(DefaultParameterSetName="Default")]
      Param(
    ...
    

    It seems that Powershell gets confused about which parameter set is in use when you use only parameters without a parameter set, and you also have defined parameter sets in your cmdlet.

    You only need to do this all of the following conditions are true:

    As explained in mklement0's answer, along with some under-the-hood information of what happens, this is possibly a bug of sorts and this solution is the workaround.