[PowerShell] Write a Custom PowerShell Cmdlet in C#

Particularly with SharePoint 2010, I have become a huge fan of Microsoft PowerShell. In addition to writing complex PowerShell scripts (.ps1 files), I have found it very useful to write my own C#-based PowerShell Cmdlets to use in my scripts.

This basic tutorial illustrates how to create a basic PowerShell Cmdlet with a couple of parameters. In the future, I will be adding addition posts about more indepth topics. However, this tutorial should get you started if you are new to writing PowerShell Cmdlets.

For this tutorial I am using Visual Studio 2010. In addition, you will need the PowerShell SDK installed (comes with the Windows 7 SDK if you have installed that instead).

  1. In Visual Studio 2010, create a new Class Library project targeted to .NET Framework 3.5 (Visual C# > Windows > Class Library). OPTIONAL: For consistency, I recommend naming the project with the name of the actions. For instance, if you want to create a “Get-MyPsCmdlet” command, name the project “MyPsCmdlet”.

  2. Delete the Class1.cs file included by default.

  3. Add a reference to System.Management.Automation.dll (you will need to browse to the assembly at C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0).

  4. In the Solution Explorer right-click the project name and select Add > Class.

  5. Create a new class named with the command and the verb. For instance, for “Get-MyPsCmdlet” name your class file “MyPsCmdletGet.cs”.

  6. Add “System.Management.Automation” in the usings statements and set the basetype of the class to Cmdlet as follows:

    using System;
    using System.Management.Automation;
    
    namespace MyPsCmdlet
    {
        [Cmdlet(VerbsCommon.Get, "MyPsCmdlet")]
        public class MyPsCmdletGet : Cmdlet
        {
    
        }
    }
  7. Above the class declaration, you will notice “[Cmdlet(VerbsCommon.Get, "MyPsCmdlet")]“. In these properties you can define the name, verb, default parameter set, etc., of the Cmdlet. Using the “Get” common verb and “MyPsCmdlet” will result in a command of “Get-MyPsCmdlet”. There are a number of common verb sets that you may use. For consistence with help documentation and localization, it is important to use a common verb whenever possible. If a common verb does not fit your needs, you can populate that value with a string of your choice.

    Verb Sets:

    • VerbsCommon
    • VerbsCommunications
    • VerbsData
    • VerbsDiagnostic
    • VerbsLifecycle
    • VerbsOther
    • VerbsSecurity
  8. To add your code to run when the command is executed, simply override the “ProcessRecord()” method:

    using System;
    using System.Management.Automation;
    
    namespace MyPsCmdlet
    {
        [Cmdlet(VerbsCommon.Get, "MyPsCmdlet")]
        public class MyPsCmdletGet : Cmdlet
        {
            protected override void ProcessRecord()
            {
                // Your code goes here
            }
        }
    }
  9. In the Cmdlet you can write text to the console like any other console application with “Console.Write” or “Console.WriteLine”. However, most PowerShell Cmdlets return objects. Here we have a simple object named “MyObject” that we are returning to the console:

    using System;
    using System.Management.Automation;
    
    namespace MyPsCmdlet
    {
        [Cmdlet(VerbsCommon.Get, "MyPsCmdlet")]
        public class MyPsCmdletGet : Cmdlet
        {
            protected override void ProcessRecord()
            {
                var myobj = new MyObject()
                                {
                                    Name = "My Object",
                                    Created = DateTime.Now
                                };
    
                WriteObject(myobj);
            }
        }
    
        public class MyObject
        {
            public string Name { get; set; }
            public DateTime Created { get; set; }
        }
    }
  10. With PowerShell Cmdlets you can add parameters of just about any .NET type. In this instance:

    • “public SwitchParameter CreatedTomorrow” is used to define a flag parameter for the Cmdlet. There is no value passed, it simply exists or does not exists. For example: “Get-MyPsCmdlet -CreatedTomorrow”.
    • “public MyObject MyObj” is used to create a parameter that requires an object with “MyObject” as the type. For example: “$myobj = Get-MyPsCmdlet”, then “Get-MyPsCmdlet -MyObj $myobj”.
    • “public string ObjectName” is used to create a parameter that requires a string. For values with spaces, use quotations around the string.
    using System;
    using System.Management.Automation;
    
    namespace MyPsCmdlet
    {
        [Cmdlet(VerbsCommon.Get, "MyPsCmdlet")]
        public class MyPsCmdletGet : Cmdlet
        {
            [Parameter(Mandatory = false)]
            public SwitchParameter CreatedTomorrow;
    
            [Parameter(Mandatory = false)]
            public MyObject MyObj;
    
            [Parameter(Mandatory = false)]
            public string ObjectName;
    
            protected override void ProcessRecord()
            {
                var myobj = new MyObject()
                                {
                                    Name = "My Object",
                                    Created = DateTime.Now
                                };
    
                if (CreatedTomorrow.IsPresent)
                    myobj.Created = DateTime.Now.AddDays(1);
    
                if (!string.IsNullOrEmpty(ObjectName))
                    myobj.Name = ObjectName;
    
                if (MyObj != null)
                    myobj = MyObj;
    
                WriteObject(myobj);
            }
        }
    
        public class MyObject
        {
            public string Name { get; set; }
            public DateTime Created { get; set; }
        }
    }
  11. Now that we have our Cmdlet writen, we can build and run it. In Visual Studio, build the project.

  12. Open PowerShell.

  13. Import the assembly using Import-Module:

    Import-Module C:\Files\Projects\MyPsCmdlet\MyPsCmdlet\bin\Debug\MyPsCmdlet.dll
  14. Run the Cmdlet:

    Get-MyPsCmdlet

That’s it. You now have a fully functional PowerShell Cmdlet. Stay tuned for more advanced PowerShell Cmdlet posts.

John Chapman

Hello, I'm John Chapman. I am a SharePoint Developer for Sitrion (formerly NewsGator) living in Denver, Colorado. I develop solutions using SharePoint and .NET, and I thrive on the challenge of writing code to overcome the impossible, annoying, or otherwise difficult obstacles.

More Posts - Website - Twitter - LinkedIn - Google Plus