Thursday, October 26, 2006 2:17 PM bart

PS - Creating Cmdlets with parameter sets (ParameterSetName)

Introduction

End of October 2006, the PowerShell release is coming closer day after day. Time for a series of lightning posts with small yet useful tips for developers targeting PowerShell with custom providers, cmdlets, etc. After reading this series, there are no excuses left for not taking on the PowerShell challenge :-).

In this first post, you'll learn how to parameterize cmdlets in a structed way.

Code

Assume you have a cmdlet called Bar that processes Foo objects:

class Foo
{
   private int
id;

   public int
Id
   {
      get { return
id; }
      set { id = value
; }
   }

   private string
name;

   public string
Name
   {
      get { return
name; }
      set { name = value
; }
   }

   //
   // Other properties and class members omitted.
   //
}

Assume our cmdlet is declared as follows:

[Cmdlet("Process", "Foo", DefaultParameterSetName = "FooId")]
public class StopProcCommand :
PSCmdlet
{
}

The DefaultParameterSetName property will be explained in a minute.

There are many ways to provide Foo objects to the cmdlet. One way is to pass the objects (e.g. obtained through some get-foo cmdlet) directly via the pipeline:

private Foo[] foos;

[
Parameter(
   ParameterSetName =
"InputObject"
,
   Mandatory =
true
,
   ValueFromPipeline =
true

)]
public
Foo[] InputObject
{
   get { return
processNames; }
   set { processNames = value
; }
}

Another way is to allow users to specify the names of the Foo objects that have to be processed:

private string[] names;

[
Parameter(
   ParameterSetName =
"FooName"
,
   Mandatory =
true
,
   ValueFromPipelineByPropertyName =
true
,
   ValueFromPipeline =
true
)]
public string
[] Name
{
   get { return
names; }
   set { names = value
; }
}

Or what about the identifiers:

private int[] ids;

[Parameter
(
   ParameterSetName =
"FooId"
,
   Mandatory =
true
,
   ValueFromPipelineByPropertyName =
true
,
   ValueFromPipeline =
true
)]
public int
[] Id
{
   get { return
ids; }
   set { ids = value
; }
}

All these parameters have one thing in common: the use of a ParameterSetName property. The idea is simple: each "parameter set" represents a different way to pass parameters to the cmdlet. On invocation, such a parameter set is chosen (e.g. by invoking process-foo -Name ... or implicitly by using the pipeline). Afterwards, you can find out about the parameter set being used by calling the ParameterSetName property of the cmdlet itself:

protected override void ProcessRecord()
{
   switch
(this.ParameterSetName)
   {
      case "InputObject":
         // Use foos
         break
;
      case "FooName"
:
          
// Use names
         break;
      case "FooId"
:
         // Use ids
         break
;
      default
:
         throw new ArgumentException("Invalid parameter set."
);
   }
}

This way you can allow different types of invocations of a cmdlet, clearly distinguishing different parameter sets. The DefaultParameterSet is used whenever the PowerShell shell cannot disambiguate a parameter that is set based on the command-line input (a fall-back mechanism that is).

Enjoy!

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Filed under:

Comments

# Windows PowerShell 2.0 Feature Focus - Script cmdlets

Saturday, March 22, 2008 9:09 AM by B# .NET Blog

Two weeks ago I did a little tour through Europe spreading the word on a couple of our technologies including