
9 April A colleague and I held a presentation about Windows PowerShell. We discussed how to use it and how you can customize PowerShell. I didn’t quite have enough time to explain the whole deal on customization, so I’m going to do that in a series of posts.
The preliminary table of contents for the series looks like this:
- Part 1: Introduction to extending PowerShell
- Part 2: Designing commandlets
- Part 3: Extending PowerShell with providers
- Part 4: Hosting PowerShell
There will probably be more parts, however this is what I’m planning on writing about now.
Introduction to PowerShell customization
PowerShell can be extended in a number of ways, you can for example extend the shell with new commands and providers to access specific datastores. You can also host PowerShell in your own application and write your own user interface for it.
The core of customizing PowerShell is snapins. A snap-in is a .NET assembly with a special installer class in it that registers the contents of the .NET assembly with PowerShell.
Setting up the references
To be able to create a new snap-in for PowerShell you are going to need an assembly reference to System.Management.Automation which lives in the global assembly cache. Getting a reference to it can be somewhat tricky.
On some windows installations with the Windows SDK installed you can see the assembly in the list of available references when you select Add reference in visual studio. However I discovered that on all three systems I use there’s no such thing and I had to rely on the better hack and slash work in MSBuild scripts. The easiest way to get a reference to the mentioned assembly is to right-click on the project in visual studio and select unload. After that you add the reference in the <References> section. This will look something like this:
<ItemGroup> <Reference Include="System" /> <Reference Include="System.Configuration.Install" /> ...
<Reference Include="System.Management.Automation" />
I’m using visual studio 2008 which adds a bunch more references, but these three are the essential ones.
The last step is to reload the project by right-clicking on the project and choosing reload project. This will load the project back in visual studio with the new reference added. There should be no yellow exclamation marks with any of the reference.
Writing your first snap-in
The second step in extending PowerShell is to write the snap-in class. A snap-in looks like this:
/// <summary> /// Powershell extension installer class /// </summary> [RunInstaller(true)] public class PowerShellExtension : PSSnapIn { /// <summary> /// Gets the description. /// </summary> /// <value>The description.</value> public override string Description { get { return "Provides access to files using the open packaging format"; } } /// <summary> /// Gets the name. /// </summary> /// <value>The name.</value> public override string Name { get { return "OpenPackagingExtensions"; } } /// <summary> /// Gets the vendor. /// </summary> /// <value>The vendor.</value> public override string Vendor { get { return "Willem Meints"; } } }
A snap-in has to inherit from PSSnapIn which defines some basic installation instructions that are required for PowerShell to be able to access the snap-in components. Because this is essentially an installer class you will need to add the RunInstaller attribute.
There are three properties that are required. The first one is the name, the name has to be a String with no spaces in it. You are allowed to use dots to separate the naming parts. Microsoft uses a naming pattern like this:
- Microsoft.PowerShell.Host
- Microsoft.PowerShell.Management
I used a rather quick and dirty variant for sample purposes, in production it is best to follow the pattern that Microsoft uses. This makes the snap-in a lot easier to identify. The other two properties, description and vendor are there to provide some basic information on who created the snap-in and a description of what it contains or does for the user.
Installing the snap-in
This one is fun, because installation differs depending on the PowerShell version you use and the windows version you have. The differences occur between x64 and x86 systems. And to make it even better, on x64 you can also choose to use the x86 version of PowerShell.
To install the snap-in on the x86 edition of PowerShell you invoke installutil from %WINDOWSDIR%Microsoft.NetFrameworkv2.0.50727
This will install the snap-in and make it available to the x86 edition of PowerShell. For the x64 edition you need to run installutil from the Framework64 directory. After installing the snap-in you can enable it in PowerShell by typing the following command:
Add-pssnapin –name <name of the snapin>
The snap-in will now be enabled for the current power-shell session. You can view which snap-ins are available with the following command:
Get-pssnapin
This will show all enabled snap-ins. To view the registered snap-ins you need to add the –Registered parameter to the commandlet.