Creating and using Cmdlets
In the past, each system or application would have its own set of tools used to manage it. Each tool had its own nomenclature, input, and output methods, and differing levels of manageability. In PowerShell, this all changes with Cmdlets.
PowerShell creates a consistent run-time for toolsets to be created that function and operate in a consistent manner. Input parsing, error presentation, and output formatting are all managed via PowerShell. This means that the developer does not need to spend a large amount of time filtering input and guessing at the output the administrator needs.
Cmdlets allow you to use the full power of custom C# code, without having to worry about input or output functions. Cmdlets also utilize native .NET
framework classes that allow for managed code and working with objects.
This section shows how to use Visual Studio to create a custom Cmdlet and then utilize the functions exposed in that Cmdlet. Specifically, we will be creating a Cmdlet that queries the performance counters on a system and returns how long the system has been online.
Getting ready
Unlike functions and modules, to create a Cmdlet we require specialized tools. The first item we need is Visual Studio. If you don't have Visual Studio currently, there are "express" versions available that provide a free, but limited feature set. Alternatively, you can use the command line if you are familiar with compiling .NET
classes from command line.
Additionally, you will need to download and install the Windows SDK. The SDK provides several system and .NET
components necessary to create our Cmdlet.
How to do it...
Carry out the following steps:
Open Visual Studio and select to create a new Class Library project.
Import the references.
In Solution Explorer, right-click on References and then we select Add Reference. On the Browse tab, browse to
C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\v3.0\ and select System.Management.Automation.dll
.In Solution Explorer, we right-click on References and then we select Add Reference. On the .NET tab, select System.Configuration.Install.
Solution Explorer should now look similar to the following screenshot:
Add Cmdlet code:
[Cmdlet(VerbsCommon.Get, "Uptime")] public class GetUptimeCommand : Cmdlet { protected override void ProcessRecord() { using (var uptime = new PerformanceCounter("System", "System Up Time")) { uptime.NextValue(); WriteObject(TimeSpan.FromSeconds(uptime.NextValue())); } } }
Add specific items for creating a Cmdlet:
[RunInstaller(true)] public class GetUptimePSSnapIn : PSSnapIn { public GetUptimePSSnapIn() : base() { } public override string Name { get { return "GetUptimePSSnapIn"; } } public override string Vendor { get { return "Ed"; } } public override string Description { get { return "Returns the uptime of the system"; } } public override string VendorResource { get { return "GetUptimePSSnapIn,Ed"; } } }
Compile the project.
On the Menu bar, select Build | Build GetUptime
If the folder for the module doesn't exist yet, create the folder.
$modulePath = "$env:USERPROFILE\Documents\WindowsPowerShell\Modules\GetUptime" if(!(Test-Path $modulePath)) { New-Item -Path $modulePath -ItemType Directory }
Copy
GetUptime.dll
from the output of Visual Studio to the new module folder.$modulePath = "$env:USERPROFILE\Documents\WindowsPowerShell\Modules\GetUptime" Copy-Item -Path GetUptime.dll -Destination $modulePath
In a PowerShell console, execute
Get-Module –ListAvailable
to list all the available modules:Use the Cmdlet by calling the included commands:
How it works...
In the first step, we are creating a Visual Studio project for a class library. In this instance, I used Visual C# due to both to personal preference and the fact that there is more information available for creating Cmdlets with C#. Visual Basic could have been used as well.
Note
I configured the Visual Studio session as a .NET
framework 2.0 project. This could have been 3.0, 3.5, or 4.0 instead.
In the second step, we add the necessary references to create and install our Cmdlet. The first reference—System.Managment.Automation.dll
—loads the necessary components to tag this project as a Cmdlet. The second reference—System.Configuration.Install
—loads the components necessary to install the Cmdlet on a system.
In the third step, we add the code for our Cmdlet. The code section can be broken into four sections: class attribute, class, ProcessRecord, and C# code.
The Cmdlet code begins with the line
[Cmdlet(VerbsCommon.Get, "Uptime")]
, which is an attribute that describes the class and what it does. In this case, it defines the class as a PowerShell Cmdlet with a verb-noun pair ofGet-Uptime
.The
GetUptimeCommand
class is a standard C# class and inherits from theCmdlet
class.The
ProcessRecord
is the section that is executed when the Cmdlet is called. There is also an optionalBeginProcessing
andEndProcessing
section that can be added to provide a build-up and tear-down process. The build-up and tear-down can be used to load information before processing and clear out variables and other objects when done processingThe C# code is the basic code and can be almost anything that would normally be included in a class project.
In the fourth step, we create the Cmdlet installer named GetUptimePSSnapin
. The installer is a fairly simple class, similar to the Cmdlet class, which inherits the PSSnapin
class and contains overrides that return information about the Cmdlet. In many scenarios, this section can be copy/paste into new projects and simply updated to reflect the new Cmdlet name.
In the fifth step, we compile the project. It is important to review the output from Visual Studio at this point to ensure no errors are reported. Any errors shown here may stop the project from compiling correctly and stop it from functioning.
Next, we create a folder to hold the compiled Cmdlet. This process is the same as we performed in the Creating and using modules recipe.
Lastly, we execute our commands to confirm the module loaded properly.
There's more
Cmdlet naming convention: Cmdlets are traditionally named in a verb/noun pair. The verb describes the action, such as get, set, or measure. The noun describes that object the action is being performed on or against. It is best practice to build functions and Cmdlets using this same naming convention for easy use.
For more information about which verbs are available and when they should be used, run Get-Verb
from within PowerShell.
See also
For more information on creating Cmdlets, see http://msdn.microsoft.com/en-gb/library/windows/desktop/dd878294(v=vs.85).aspx