Question

I have the following code, where I try to create a custom Cmdlet for PowerShell using C#.

What I want to do with my custom cmdlet is that, user should call it with two parameters, from which first one should be -Text or -File or -Dir, and the next one should be a value, a string which specifies the value for text, or file, or directory.

The point is that if I try to call my cmdlet with a parameter -Test for example, which is of course a wrong parameter, I don't get the value of the default statement, which says "Bad parameter name".

I guess my code just don't get till the default part of the switch.

By the way, SHA256Text, SHA256File, and SHA256Directory, are just custom helper methods that I have written, so don't worry about them.

using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
using System.Management.Automation;

namespace PSSL
{
    [Cmdlet(VerbsCommon.Get, "SHA256")]
    public class GetSHA256 : PSCmdlet
    {
        #region Members

        private bool text;
        private bool file;
        private bool directory;
        private string argument;

        #endregion

        #region Parameters

        [Parameter(Mandatory = true, Position = 0, ParameterSetName = "Text")]
        public SwitchParameter Text
        {
            get { return text; }
            set { text = value; }
        }

        [Parameter(Mandatory = true, Position = 0, ParameterSetName = "File")]
        public SwitchParameter File
        {
            get { return file; }
            set { file = value; }
        }

        [Parameter(Mandatory = true, Position = 0, ParameterSetName = "Directory")]
        public SwitchParameter Dir
        {
            get { return directory; }
            set { directory = value; }
        }

        [Parameter(Mandatory = true, Position = 1)]
        [ValidateNotNullOrEmpty]
        public string Argument
        {
            get { return argument; }
            set { argument = value; }
        }

        #endregion

        #region Override Methods

        protected override void ProcessRecord()
        {
            switch(ParameterSetName)
            {
                case "Text":
                    SHA256Text(argument);
                    break;

                case "File":
                    SHA256File(argument);
                    break;

                case "Directory":
                    SHA256Directory(argument);
                    break;

                default:
                    throw new ArgumentException("Error: Bad parameter name.");
            }
        }

        #endregion
    }
}
Was it helpful?

Solution

Since PowerShell does not have enough information to 'bind' to the parameters, ProcessRecord is not called at all, and instead gives an error. So you never see your switch getting executed.

Parameter set cannot be resolved using the specified named parameters. + CategoryInfo : InvalidArgument: (:) [], ParameterBindingException + FullyQualifiedErrorId : AmbiguousParameterSet,

You should not even want to. Let PowerShell handle the parameters. You can fix your CmdLet by doing the following:

  1. Remove the Position = 0 for the SwitchParameters. It's not logical to have positional SwitchParameters. PowerShell can detect SwitchParameters with ease in any position
  2. Do not make the SwitchParameters mandatory. It is of no use. The switch is either there or not, true or false. Forcing it to be there does not make sense. It's like forcing it to be true.
  3. Give your CmdLet a DefaultParameterSetName. Logical would be to chose one of the defined parameter sets, like 'Text'
  4. Make your Argument parameter Position = 0. Since the SwitchParameters don't need a position this is the first.

Now you can call it like this:

Get-SHA256 'SomeText'
Get-SHA256 'SomeText' -Text
Get-SHA256 -Text 'SomeText'
Get-SHA256 'C:\Some.File' -File
Get-SHA256 -File 'C:\Some.File'
etc

Also consider checking the SwitchParameters values instead of switching on the ParameterSetName. SwithParameters can be called like -File:$false. Fall back to your default.

OTHER TIPS

Lars is correct. The parameter binder is a separate procedure external to your cmdlet. If the syntax is not correct, the cmdlet is not even executed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top