![]() |
Platforms, Frameworks & Libraries »
Vista API »
General
Intermediate
Build a PowerShell cmdletBy Shahar GvirtzLearn how to build a simple Windows PowerShell cmdlet, use parameters, wildcards, CustomPSSnapin and the Extended Type System |
.NET 2.0, WinXP, Win2003, Vista, Visual Studio, IIS 7, Dev
|
||||||||||
|
Advanced Search |
|
|
|
||||||||||||||||
Download codeproject3.zip - 24.0 KB
Windows PowerShell (AKA Monad) is new CLI (Command Line Interface) provided by Microsoft.
PowerShell based on .NET Framework 2.0 and pass data as .NET objects.
In this article, you'll see how to develop command let (cmdlet, powershell commands) which support wildcard, and use ETS (Extended Type System) and how to use CustomPSSnapIn.
The sample use the IIS 7 and the IIS 7 .net libraries (Microsoft.Web.Administration) to reterive the list of websites in the local IIS 7 server.
Cmdlets are tiny .NET class, which derived from System.Management.Automation.Cmdlet or from System.Management.Automation.PSCmdlet and override few methods with your own logic.
These cmdlets installed to the powershell and can be used from powershell or from other applications which use the powershell to Invoke cmdlets.
Cmdlet class can derived from 2 different classes: Cmdlet and PSCmdlet. The difference is how much you depence on windows powershell environment.
When deriving from Cmdlets, you aren't really depend on powershell. You are not impacted by any changes in powershell runtime.
In addition, your cmdlet can invoke directly from any application instead of invoking it through the Windows PowerShell runtime.
In most cases, deriving from Cmdlet is the best choice except when you need fully integration with powershell runtime, access to session state data, call scripts etc. Then, you'll derive from PSCmdlet.
Every cmdlet have a name in the same template verb-noun. The verb (get,set,new,add etc.) is from built in list of verbs name. The noun, is for you'r choice.
The first part in the cmdlet class (getWebsites.cs) is:
[Cmdlet(VerbsCommon.Get, "ws" SupportsShouldProcess = true)]
The verb is "Get" (from the enum VerbsCommon), the noun is "ws" and we supports ShouldProcess.
It's very important to use the verb from one of the Enums.
Note, that in the top of the code, i have this using statement:
using System; using System.Collections.Generic; using System.Text; using System.Management.Automation; using System.Collections; using Microsoft.Web.Administration; using System.Collections.ObjectModel; using System.Diagnostics; using System.Reflection;
The bolds are the "Special" namespaces which relevant for powershell except Microsoft.Web.Administration which used to manage IIS 7.
Almost any powershell cmdlet use parameters to help users get relevant information. The parameters are, actually, properties which have ParameterAttribute before:
[Parameter(Position = 0, Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, HelpMessage = "Enter filter by site name (support wildcard)")] [Alias("SiteName")] public string Name { set { names = value; } }
Parameters can ve user by position or by property name. It's mean that if we set the parameter in position 0 you can call the cmdlet like this:
get-websites *
The "*" is the parameter, or by propery name:
get-websites -Name *Here, we also defined alias:
get-websites -SiteName *
The mandatory means that the user must enter value to this parameter.
In our cmdlet, we can override few methods. We must override at least on to this list:
The code here used, in most cases, to preapare the cmdlet. this code runs only once, when the cmdlet calls.
This is the most common overrided method. This method include the main logic. this code can run even more than once, as requied.
This overrided method used to finalize the cmdlet operation.
We can also override StopProcessing Method, which include code that will run in unexpected stop of the cmdlet (for example, the user use ctrl+c).
I override only the ProcessRecord method.
First, I create instance of the generic System.Collections.ObjectModel.Collection<> collection. This is the collection type powershell use. The type is PSObject, which is the main object powershell used.
Because we want to support wildcard, I use the buil-in wildcard classes that comes with powershell:
WildcardOptions options = WildcardOptions.IgnoreCase |WildcardOptions.Compiled;
WildcardPattern wildcard = new WildcardPattern(names, options);
Then, we create instance of Microsoft.Web.Administration.ServerManager, the object used to manage IIS 7 websites.
In the foreach loop , We check for every site if his name match the wildcard. If it is, we convert it to PSObject.
Extended Type System is one of the main and most interesting powershell concepts. it's mean that we can extend any type we just want, and add members in addition to the built in members.
The PSObject object is the main object in powershell, because it's include the original object and the extended members in the same object, and give the user or other developer who invokes this cmdlet the option to use any member - the original members and the extended one.
ps.Properties.Add(new PSNoteProperty("MaxBandwidthMB", site.Limits.MaxBandwidth / 1024));
Here, we add a new property called MaxBandwidthMB and his value is the the original bandwidh value / 1024.
Types can be extended from code, or from XML files in specific format. Here, we see example to extend type with new property - but we can add properties and methods from a lot of types: aliases, scripts, code methods etc.
Finally, we add the PSObject instance which include the original (early bound object) and the extended members to the collection, and use WriteHost method to write it to the host (can be powershell command line host, or other application that invoke our cmdlet).
After you'll finish the cmdlet, you can get a list of members of the object returns from the cmdlet. look, that here you can see our extended property (marked):

We use try...catch statement, and if exception occured we use WriteError method to write information about the error to the host.
If we use this cmdlet now from the console, we will get strange output, which include objects type and few values. We have to specify the default output view we want. We do this in the format.ps1xml file. note that we use MaxBandwidthMB property, which is extended one.
This is the output without the format file:

The snap In include the detiles powershell needs to install the cmdlet. We can derived from PSSnapIn which is the "default" - install everything you can, or from CustomPSSnapIn then we set exactly what to do.
Here, we add the cmdlet and the format file.
First, we define collection for cmdlets, formats,types,providers. in the constructor, we add the cmdlet and the format file.
We also override few properties to include information about our snapin. And, we override properties to return our collection of cmdlets and formats.
From powershell, we install the snap in with installutil.exe, part of the .NET Framework SDK.
I Wrote a little function you can add to your profile:
function installutil
{
param([string]$dllPath=$(throw "Please Enter the DLL path to Install!"))
set-alias installutil $env:windir\Microsoft.NET\Framework\v2.0.50727\installutil
if(test-path $dllPath)
{
installutil /u $dllpath
installutil $dllpath
write-host "snap-in installed. now, you can add it to your shell instance"
}
else{
write-error "The file does not exist"
}
}
Now, you just have to enter:
installutil dllPath
Instead of dllPath, enter the full path to the dll which include the dll of the project.
Now, you have to add the snap-in:
add-pssnapin cpdemo
Note that you may have to change the path of the format file in snapin.cs class.
And that's all! The cmdlet is ready to use and return Collection of PSObject which include Microsoft.Web.Administration.Site and extended property.
In PowerShell, you can use the object that the cmdlet return for more things. this command, for example, will save the output to csv file:
get-ws d* | Where{$_.MaxBandwidthMB -gt 4000000} | Select-Object Name,MaxBandwidthMB | out-csv c:\csv.csv
This command, will save new csv file which include list of the name and the MaxBandwidthMB property for all sites that theyr name begin with "d" where the value of the property MaxBandwidthMB > 4000000.
| You must Sign In to use this message board. | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 20 Oct 2007 Editor: |
Copyright 2007 by Shahar Gvirtz Everything else Copyright © CodeProject, 1999-2009 Web20 | Advertise on the Code Project |