The Problem:
I am always using PowerShell to inspect the SharePoint object
model when diagnosing problems or gathering information about an
installation. One thing that annoys me is the command to get an
SPSite object. This would be something like:
$site = New-Object Microsoft.SharePoint.SPSite("http://site")
I seem to be typing this command many times a day. It is
frustrating because there is no tab completion for the namespace
and I am hopeless at typing. So I decided to explore making a
PowerShell Cmdlet to simplify this basic task. Cmdlets (read
Command-Let) are just standard PowerShell commands like Get-Help,
Get-Process etc. We can write our own Cmdlets using managed .NET
code.
The Solution:
As this was my first Cmdlet I kept it painfully simple. I began
by downloading the Visual Studio Powershell templates from channel
9. The templates were created by MS Architect Evangelist
David Aiken. Check his blog for more info on creating
PowerShell Cmdlets using the templates and other general
Architecty/PowerShell stuff.
So the steps for creating the Cmdlet are as follows:
1.
After installing the templates create a new Visual Studio
project, use the Windows PowerShell template (duh). This creates a
SnapIn class that we will use as a vehicle to deliver the Cmdlet.
In this case we only have the one Cmdlet but we could have a whole
suite of them (more on that later). Now edit the automatically
generated file with more friendly values. The only really important
property is name. I have edited my name command to read:
public override string Name
{
get { return "SharePointCmdlets"; }
}
2.
Now add a new item to the project and use the Windows PowerShell
PSCmdlet option. This will create a Cmdlet code stub to use. I have
edited the verb and class name as required. The verb will be used
as the prefix for the command. In my case I will reference the
command in PowerShell with the syntax Get-SPSite.
[Cmdlet(VerbsCommon.Get, "SPSite", SupportsShouldProcess =
true)]
public class GetSPSite : PSCmdlet
3.
Now I want to create a property to take some input from the
console in the form of a parameter eg Get-PSSite http://test.
I have used the following code to achieve this:
private string _siteName;
[Parameter(Position = 0, Mandatory = true,
ValueFromPipelineByPropertyName = true, HelpMessage = "The URL of
the site to return")]
[ValidateNotNullOrEmpty]
public string SiteName
{
get { return _siteName; }
set { _siteName = value; }
}
4.
Now for the actual meat. I have filled out the ProcessRecord
method with code to get a reference to the SharePoint site and
write it back to the PowerShell console.
protected override void ProcessRecord()
{
try
{
using (SPSite site = new SPSite(SiteName))
{
WriteObject(site);
}
}
catch (Exception ex)
{
WriteObject("ERROR: " + ex.Message);
}
}
5.
So thats it, compile it and its ready to go. However it needs to
be registered for it actualy work in PowerShell. This is rather
easy. Open a Visual Studio command prompt and navigate to the the
bin\debug folder where the dll resides.
Run 'InstallUtil Name.dll' to make it
available in PowerShell.
Then open up PowerShell an run the following command to register
the SnapIn.
Add-PSSnapIn SharePointCmdlets
Now we can use our Cmdlet as demonstrated here:

Note that you can now use tab completion to type the command as
well.
To make things just that little bit easier I have added the snap
in register command to my profile. This way it is regiestered
automatically each time I open up PowerShell.
The profile script can be found at
C:\WINDOWS\system32\windowspowershell\v1.0\profile.ps1. My profile
script is pretty simple and looks like:
[System.Reflection.Assembly]::Load("Microsoft.SharePoint,
Version=12.0.0.0, Culture=neutral,
PublicKeyToken=71e9bce111e9429c")
Add-PSSnapIn SharePointCmdlets
cd \
So this is loading the Microsoft.SharePoint dll, registering my
Cmdlet and then setting the directory to the root.
Note that this is the global profile and will affect all users
for the machine.
Next Steps:
So this was a trivial example I know, but it demonstrates the
process and I believe it is a great starting point for bigger
things. I would like to extend this simple example and add some
more useful commands that return various stats about SharePoint
sites. It could also include some basic administrative commands.
Adding an installer is definatley on the cards. I would like to
make this a community project (hosted on CodePlex) so that other
SharePoint/Powershell enthusiasts can add useful Cmdlets and help
make everyones life easier. So watch this space for more SharePoint
Cmdlets in the near future.