Custom Powershell Cmdlets

Command line tools have always been my favorite, whether its a linux box or a windows machine. Its way cooler!! (don't know why). I use Powershell on Windows Vista and I really like for the fact that its designed in .NET environment which makes it easy to extend as you want. I am assuming you have basic information about Cmdlet and Snap-In classes for Powershell. If not, please refer to the the documentation which comes with Powershell installation.

I wanted a simple program to run in Powershell to display the temperature given the zipcode. I am going to show you how easy it is to add a new command in Powershell. A command like dir, ls etc. is called as a Cmdlet in Powershell. To use a new command in Powershell you need to do the following:

1) Create a .NET class which inherites from PSCmdlet. Add the functionality as required. This will be the custom Cmdlet class.

2) Create a new class in same namespace as the above class. The base class for this class should be PSSnapIn. This will be the custom Snap In class which is required to insert any Cmdlet in Powershell.

3) Register the Cmdlet using the SnapIn class we created.

That's it!!

Creating a Custom Cmdlet class

Nothing makes it more clear than a piece of code right. Here it goes!

using System.Management.Automation;
using System.Management.Automation.Provider;

[Cmdlet(VerbsCommon.Get,"temp")]
public class TempCmdlet : PSCmdlet
{
private string zip="60606";
[Parameter(Mandatory=false,Position=0)]
public string ZipCode
{
get
{
return zip;
}
set
{
zip = value;
}
}

public object[] GetData()
{
Service1 service = new Service1();
object[] data = service.GetWeather(ZipCode);
return data;
}

protected override void ProcessRecord()
{
object[] data = GetData();
if (data.Length == 3)
{
WriteObject("Location : " + data[0].ToString());
WriteObject("Condition : " + data[1].ToString());
WriteObject("Temperature : " + data[2].ToString()+ " F");
}
}
}

This is my custom Cmdlet class. Observe the attribute to the class. This attribute shows that the command I would issue at the prompt would be Get-temp. The first part has to be a predefined verb in the VerbsCommon definition. The second part could be anything meaningful to you.

I am using a webservice to get the weather data by passing a zipcode to it. By default its 60606. Of course you could use a data store for the same thing. If you need any parameters to your Cmdlet you should create a Property and assign an attribute called Parameter. There are a bunch of values for this attribute but I used some common ones. The important function to look out is the ProcessRecord. This function is executed when the user invokes the Cmdlet at the prompt. Writeobject function actually writes the data to the output pipeline which is displayed to the user. There are several other functions which can be effectively used to improve the output but I did not go in that detail.

Creating a SnapIn class.

To register the Cmdlet , you need a custom SnapIn class. Here it goes again.

[RunInstaller(true)]
public class TempSnapIn : PSSnapIn
{
public TempSnapIn() : base()
{
}

public override string Name
{
get
{
return "TempSnapIn";
}
}

public override string Vendor
{
get
{
return "Microsoft";
}
}
public override string VendorResource
{
get
{
return "TempSnapIn,Microsoft";
}
}

public override string Description
{
get
{
return "This is a PowerShell snap-in for the Get-temp cmdlet.";
}
}

public override string DescriptionResource
{
get
{
return "GetTempSnapIn,This is a PowerShell snap-in for the Get-temp cmdlet.";
}
}
}

Make sure you override all these properties, if not you would get some error when you try compiling this class. Place this class in the same namespace as the Cmdlet. Although I am not sure if different namespaces would work but you can try that.

Register the Cmdlet

We are ready to register our little Cmdlet created. This is the mose exciting part since we need to hit some commands in Powershell. Yessssssss!!

Open Powershell prompt.

Give the following commands.

PS> $ref = "$Env:ProgramFiles\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0\System.Management.Automation.dll"
PS> $compiler = "$env:windir/Microsoft.NET/Framework/v2.0.50727/csc"
PS> &$compiler /target:library /r:$ref Codefile.cs

Codefile.cs should be the .cs or .vb file for your classes. This is the step to compile the code, you could obviously use the IDE to do this step.

Now to actually register the Cmdlet, use the InstallUtil program.

PS>set-alias installutil $env:windir\Microsoft.NET\Framework\v2.0.50727\installutil
PS> installutil Codefile.dll

Replace the Codefie.dll with your dll created in earlier step.

Now add the Snap In we created to the shell

PS>add-pssnapin SnapInclassname
We are done!! You could check by doing Get-temp at the prompt. Do not close the windows since you would lose all the settings you just did. Instead to save the session export the console as below.
PS> export-console MyCustomShell

If you have any particular questions about the code or anything else please reply to this post.

Abhang Rane


No comments :

Post a Comment

Leave a Comment...