Thursday, January 12, 2006

Creating a MSH Snap-in with MSH B3 - Part 1

MSH Beta 3 comes with a snap-in feature, which simplifies creating additional cmdlets for your own use. I'll not go in to why developers need to create cmdlets here, hopefully that's a given (if not, I'll talk about this in another article). In this muli-part article, I plan to discuss what MSH snap-ins are, then show how easy it is to create a MSH snap-in with B3. I've also created a compile script to do the compilation and implementation of a snap-in too - which you may find useful.

First some background. In MSH, a cmdlet is a simple unit of work. MSH comes with a bunch, but you can add more (typically for some task specific reason). Exchange 12 will for example come with some like New-Mailbox, etc. You have two ways of delivering cmdlets to a user: via an extended shell (using makeshell and creating your own shell) or, new in B3, you use the snap-in feature. I plan to cover make-shell in a separate article.

To a developer, a cmdlet is a bit of code you write to do some task. Because your code will be snapping into Monad, it has to follow some simple rules. Each cmdlet implements a class that derives from a base MSH Cmdlet class. This class over rides one or more of three cmdlet methods: StartProcessing(), ProcessRecord() and EndProcessing(). Finally, you need to decorate your source code with the appropriate attributes to define your cmdlet to Monad and then compile your code. Once compiled, it's ready for deployment (details to follow in a later article).

With Beta 3, a snap-in is just a bit more code - a simple class definition giving some basic information about the snap-in - it's mainly template code (fill in the blanks). This information is then used in the compilation and installation process (in part 2)

Here is the code for a simple MSH Snap-in containing one cmdlet. It's based on the sample in the release notes:
//random.cs
using System;
using System.ComponentModel;
using System.Management.Automation;
using System.Reflection;
[assembly: AssemblyVersion ("1.2.0.1") ]
[assembly: AssemblyTitle ("Randon Numbers") ]
[assembly: AssemblyProduct ("MSH Beta 3 Testing") ]
[assembly: AssemblyCompany ("QA plc") ]
namespace QACmdletSnapins
{
// This class defines the properties of a snap-in
[RunInstaller(true)]
public class QARandomNumberSnapin : MshSnapIn
{
///

Creates instance of DemonSnapin class.
public QARandomNumberSnapin() : base(){ }
///Snapin name is used for registration
public override string Name
{ get { return "QARandomNumberSnapin";} }
/// Gets vendor of the snap-in.
public override string Vendor
{ get { return "QA, Thomas Lee";}}
/// Gets description of the snap-in.
public override string Description
{ get{ return "Contains a cmdlet to generate random number";}}
}
/// An implementation of a random number generator.
[Cmdlet("Get", "Random")]
public class QAGetRandomCommand : Cmdlet{
protected override void EndProcessing(){
Random r = new Random();
WriteObject(r.Next());
}
}
}

I plan to post a better laid out version to www.reskit.net/monad/samplescripts. Looking at this C# program, it starts with standard using clauses, then some important assembley attributes. The snap-in Namespace is QACmdletSnapins, and it defines a single class - QARandomNumberSnapin, over-riding the base MshSnapIn class. There are then 4 public strings (and the attribute) and that's done your snap-in definition.

The Snap-in program finishes up with, in this case, a single cmdlet although you can put multiple cmdlets into a single snap-in. It's called Get-Random, and is implemented by a class called QAGetRandomCommand which derives from the base MSH Cmdlet class. Plus the necesary Attribute to define the cmdlet to MSH.

In terms of writing the cmdlet/snap-ins that's it. It's really very staightfoward! I'll cover compiling and deploying your new snap-in in a future article. Hopefully that's whetted your appetite for more!!

No comments: