Saturday, June 5, 2010

Powershell, Versions, Modules & Snap-ins

I've been working on a Powershell script that will soon ship as part of a product. As such, it has requirements that it must meet, and I started development on the wrong end of that spectrum.


I mean, Powershell is Powershell, right? Well, yes. But Powershell v1.0 is not Powershell v2.0 and the differences are both subtle and important. Especially when it comes to using Modules (DLLs) and Snap-ins.


My first problem was that I started development on my Windows 7 64-bit laptop with Powershell 2.0. The first important takeaway from this experience:


1. Developing in Powershell 2.0 is better than Powershell 1.0.


And the second:


2. The Powershell ISE (Integrated Scripting Environment) may be the best tool I've used for developing scripts.


It's no Eclipse, but it's very handy and the price is right.


Anyway, the script I'm writing integrates with System Center Operations Manager 2007 (aka SCOM and OpsMgr). SCOM delivers an SDK that's available both on the management server and the console, so my script will be running in one of those two locations and relying on several different OpsMgr assemblies, including:

  • Microsoft.EnterpriseManagement.OperationsManager.dll
  • Microsoft.EnterpriseManagement.OperationsManager.Common.dll
  • Microsoft.EnterpriseManagement.OperationsManager.ClientShell.dll
and one system assembly:
  • System.Security
My troubles were heavily rooted in a combination of me not knowing Powershell, trying to cobble things together from snippets of code found on the web and in books, and starting off in the wrong version of Powershell running on the wrong "bitness" OS.


I needed to build this script so it would run in Powershell v1.0 and it needs to run on both 32-bit and 64-bit platforms. Finally, I got it working on v2.0 and 64-bit, but then started down a path of misery trying to make it backwards compatible. Along the way I learned a few things:

  • Modules/DLLs can get loaded in several ways.
  • Snap-ins need two key steps to work in your script -- they need to be registered with this system, which is the first step, then added to the script context you're working on.

Loading Modules/DLLs:

VERSION 2 ONLY: import-module "C:\Program Files\System Center Operations Manager 2007\Microsoft.EnterpriseManagement.OperationsManager.ClientShell.dll"
VERSION 1 & 2: [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.
EnterpriseManagement.OperationsManager")


Register your Snap-ins with the OS:

So this was an odd concept for me to finally get my head around. When you register your snap-in with the system, you're creating an entry in the system registry that describes the snap-in. This does NOT make the cmdlets available to your script. I didn't really grasp this until I understood the difference between Get-PSSnapins and Get-PSSnapins -Registered. More on this in a moment...


First, to get your Snap-in recognized by the system, you need to use the InstallUtil.exe utility. This is located in C:\Windows\Microsoft.NET\Framework\v2.0.50727\installutil.exe. Unfortunately, the actual path will vary with the bitness of your OS (Framework becomes Framework64 on 64-bit OSes) and with the version of .NET Framework embedded in the path, you will also have versioning of the framework to deal with.


In order to determine if your Snap-in registration was successful, you can either go check in the registry (A Registry key with SnapinName, which was defined in the PSSnapIn class, will be created under HKLM\Software\Microsoft\PowerShell\1\PowerShellSnapIns) or you can run Get-PSSnapins -Registered. Remember, this does NOT make the cmdlets available to your script...yet.


To make the cmdlets available to your script, you need to add them with Add-PSSnapins. At this point, the Get-PSSnapins command (no -Registered option) should tell you that your snap-in is loaded into the script context. And depending on the snap-in, you may need to source another script (.ps1) that includes the cmdlet function names, as was true in this case: &"C:\Program Files\System Center Operations Manager 2007\Microsoft.EnterpriseManagement.OperationsManager.ClientShell.Functions.ps1"

I don't know if this is enough information or even presented clearly enough to help, but here's hoping. Also, you should check out the page that ultimately helped me decode this riddle (with thanks to Arul Kuramavel and the good people at Wrox): http://www.wrox.com/WileyCDA/Section/Extending-Windows-Powershell-with-Snap-ins.id-320555.html

No comments:

Post a Comment