Creating Custom PowerShell Cmdlets for SharePoint

Something that a lot of people don’t realize with PowerShell for SharePoint is that it only provides cmdlets down to the list level. Meaning that you do not have any Powershell cmdlets available out-of-the-box to help you interact with Lists and below (e.g. Items, Fields, etc). In order to interact with these, you need to understand the SharePoint Object Model and this very often requires some high level development skills, which unfortunately is not something a lot of IT Pros have. For example, you can use the following cmdlet to get a reference to the root SharePoint web on http://localhost:

​$web = Get-SPWeb http://localhost
But if you wish to get a reference to the library “Documents” that exist under that web, you’ll need to call the List property on the object and reference its collection to get the appropriate reference back (see code below):
​$list = $web.Lists[“Documents”]
​While this may prove to be obvious for some, it is not a syntaxt most administrators will be used to, as it forces you to switch your mindset from a typical scripting logic to an object oriented one. Wouldn’t it be cool if there was a Get-SPList cmdlet available? Well friends, there is always the option to build it our selves, and this is exactly what this blog post will be covering. Off course my goal here is not to steal the thunder from fellow @GLapointe​ who’s been offering a list of such custom cmdlets (including his version of Get-SPList). My goal is to teach you all how to do it yourselves.

​​What do I need?

​A development machine that has both Visual Studio and SharePoint (any version) installed on. Yes, that’s right, there will be Visual Studio development involved. Basically, what we will do is created a new assembly (.dll) file that will be imported into our Powershell session and that will exposed methods as cmdlets (methods such as Get-SPList).

​​​Code

​We will start by creating a new C# Class Library project in Visual Studio. For the sake of this example, I’ve used Visual Studio 2013 with update 2, but really, any version supporting .NET 3.5 will do. The first thing you will need to do with your Visual Studio project is add references to the PowerShell core assemblies. These are System.Management and System.Management.Automation. The first one should be part of the default Visual Studio list of available assemblies in the GAC, while the second one will be located under C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0. ​We also need to make sure we add a reference to the Microsoft.SharePoint assembly because our PowerShell cmdlet will ultimately require us to interact with SharePoint (see Figure 1).
SolExplorerSPPS.png
Figure 1 – Solution Explorer showing referenced Assemblies and default class
Next, we will need to make our main class inherit from the Cmdlet class. This is what will allow Powershell to recognize that the methods and logic included in our class is to be exposed as a cmdlet. For my example, I named my main class GetSPList to make it clear that the code it contain was to expose the Get-SPList cmdlet. The next thing you’ll need to do in you code, is to declare your class as a cmdlet by specifying the verb to use, and the noun. In our case, our verb is “Get” and our noun “SPList, meaning that our cmdlet will be accessed using the Get-SPList method (see blue line below).
​After declaring our class as a cmdlet, we need to specify what parameters our method will accept. This is done by declaring class variables as being cmdlet parameters (see green lines). For each paramter, we will need to mention what their default input order should be, and mention if they are mandatory or not.
​Last but none the least, we need to override the ProcessRecord method (line in orange), which is the method that truly performs an action based on the parameters that were passed. In our case, We will use the URL received to create a new SPWeb object, we will get a reference to a list it contains using either its name (because we’ve specified string as the variable type, we should use GUID if we want to access the list based o a GUID), and will return the list instance.
​​​​using System;

using System.Management;
using System.Management.Automation;
using Microsoft.SharePoint;
 
namespace SPPS
{
    [System.Management.Automation.Cmdlet(System.Management.Automation.VerbsCommon.Get, “SPList”)]
    public class GetSPList:Cmdlet
    {
        [System.Management.Automation.Parameter(Position = 0, Mandatory = true)]
        public string Web;
        [System.Management.Automation.Parameter(Position = 1, Mandatory = true)]
        public string List;
        protected override void ProcessRecord()
        {
            using(SPSite site = new SPSite(this.Web))
            {
                using(SPWeb web = site.OpenWeb())
                {
                    SPList list = web.Lists[this.List];
                    this.WriteObject(list, false);
                }
            }
        }
    }
}​
​​​​​All that is left now is to compile​ our code into a reusable assembly (.dll file). In my case I’ve copied the resulting SPPS.dll file into the C:\Script\ repository on my development machine.

Make PowerShell Use Our Custom Cmdlet

To tell PowerShell to load the logic contained in our custom assembly, we will need to use the Import-Module  and reference the custom .dll. In my case, I will be calling the following line of Powershell to load my assembly in the session:
Import-Module c:\Script\SPPS.dll
Once this is done, I can verify that everything is working as expected by calling the Get-SPList cmdlet that is contained within that assembly. Figure 2 below shows a PowerShell session in which I have loaded my custom assembly and used my custom PowerShell cmdlet to get a reference to the library “Documents” located at the root of the http://localhost site collection.
SPPSGetListInAction.png
Figure 2 – Using a custom PowerShell cmdlet to get a reference to a SharePoint list.
What we’ve just learned in this article is extremely powerfull and can be extended to bridge many gaps that currently exist in the SharePoint/PowerShell world. Before you dig too deep in this, however, I recommend taking a look at what Gary Lapointe has already made available to us all on his site (visit Gary’s site). Enjoy!

Microsoft Premier Field Engineer – SharePoint

Leave a Comment

Your email address will not be published. Required fields are marked *

*
*