« Let's All Write a Cmdlet | Main | Monad documentation pack available »

October 02, 2005

Let's All Write a Cmdlet, Part 2

The first cmdlet example was pretty basic and didn't really show the advantages of writing a cmdlet. So this is a more relevant example. Put the following in the adam.cs file you created before (or make a new file with it), then compile the source and make-shell as before:

  [Cmdlet("palindromify","name",SupportsShouldProcess=true)]
  public sealed class PalindromifyNameCmdlet : Cmdlet
  {
    [Parameter(Position=0,Mandatory=true,ValueFromPipeline=true,ValueFromPipelineByPropertyName=true)]
    public string Name
    {
      get { return _name; }
      set { _name = value; }
    }
    private string _name;

    protected override void ProcessRecord()
    {
      if (ShouldProcess(Name)) {
        char[] name_array = Name.ToCharArray();
        System.Array.Reverse(name_array);
        string reversed_name = new string(name_array);
        string palindrome = "I saw " + Name + ", " + reversed_name + "was I";
        WriteObject(palindrome);
      }
    }
  }

This defines a cmdlet called palindromify-name which takes a single parameter called Name. So at its most basic it works like this:

MSH> palindromify-name -name foofa
I saw foofa, afoof was I

But what do the other parts do? Well:

  1. The Position=0 metadata means you can type the parameter without specifying -Name:

    MSH> palindromify-name foofa

  2. The Mandatory=true metadata means if you type the cmdlet with no parameter, it prompts you:

    MSH> palindromify-name

    Cmdlet palindromify-name at command pipeline position 1
    Supply values for the following parameters:
    Name:

  3. The ValueFromPipeline=true metadata tells it to bind the entire pipeline object to the parameter--this means you can pipe any string in to it:

    MSH> "evian" | palindromify-name

  4. The ValueFromPipelineByPropertyName=true metadata tells it to bind any input object *property* that is called Name to the Name parameter; process objects are one example of an object with a Name property:

    MSH> get-process adamsh | palindromify-name

  5. Finally, the SupportsShouldProcess=true cmdlet-level metadata, along with the call to ShouldProcess() before the cmdlets does anything, gives you the following:

    MSH> "murder" | palindromify-name -whatif
    What if: Performing operation "palindromify-name" on Target "murder".

    (-whatif shows what would happen, without actually performing the operation) and

    MSH> "amanaplanacanalpanama" | palindromify-name -confirm

    Confirm
    Are you sure you want to perform this action?
    Performing operation "palindromify-name" on Target "amanaplanacanalpanama".
    [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help
    (default is "Y"):

    (-confirm asks you before processing objects; as with -whatif, it makes a bit more sense if you pipe in something that produces a lot of objects that either are strings or have a string property called Name. get-process or get-childitem would work in this example, as would a simple array, as in: ("foo","bar","ertegun") | palindromify-name.)

Posted by AdamBa at October 2, 2005 10:31 PM

Trackback Pings

TrackBack URL for this entry:
http://proudlyserving.com/cgi-bin/mt-tb.cgi/332

Comments