Summary: How do I use snap-ins with the Windows PowerShell 2.0 cmdlet, Add-Module? What are the benefits of using this method over Add-PSSnapin?
Microsoft Scripting Guy Ed Wilson here. I am on holiday and am speaking at SQL Saturday #49 today in Orlando, Florida. The really cool thing about this particular SQL Saturday is that they have an entire track devoted to Windows PowerShell. This means you could come and spend the whole day learning about Windows PowerShell—way cool! Luckily, today we have Tome Tanasovski as our guest blogger, and Tome will discuss using Windows PowerShell modules.
Tome is a Windows engineer for a market leading global financial services firm in New York City. He is the founder and leader of the New York City PowerShell User Group, a blogger, and a regular contributor to Microsoft's Windows PowerShell forum. He is currently working on the Powershell Bible, which is due in June 2011 from Wiley.
Take it away Tome!
When I was a child, I knew where the sugar cubes were hidden. I knew that if I opened the left cupboard above the sink, reached my arm to the very back corner, and then moved my hand exactly three jars of tea to the right, I would find the box that held the most precious jewels of dissolving sweetness a five-year-old boy could ever want. Unfortunately, there were physical limitations in the way that prevented me from reaching this treasure trove of candy whenever I desired; my legs and arms were just too short. During that time in my life, my only option was to ask my mother if I could have one sugar cube, and fortunately for me on occasion, she would say yes.
Windows PowerShell 1.0 also had a treasure trove of “sugary” snap-ins. Unfortunately, in order to use a snap-in, you must also ask your “mother” (an administrator) to put the snap-in on your computer. I am sure the rest of you share my desire to be allowed to corrupt your pristine teeth and Windows PowerShell session without interference from mommy. Fortunately, just as my arms and legs would eventually grow so that I could reach the cupboard, Windows PowerShell has also matured with the release of version 2.0. You no longer need to register a snap-in’s DLL before you can use it. The trick is to treat the snap-in as a binary module. In order to do this you point the Import-Module cmdlet to the DLL of your favorite snap-in:
Import-Module -Name c:\snapins\ScriptingGuy\ScriptingGuy.dll
This will work as expected in most scenarios. Let’s explore the exceptions so that we can understand why they do not work with the above method. First, let’s look at the Quest AD cmdlets. If you run the following from the installation directory of the Quest snap-in, it will appear to load correctly:
Import-Module -Name .\Quest.ActiveRoles.ArsPowerShellSnapIn.dll
However, when we start to use the cmdlets, we begin to see a difference between the output that is returned via the module method…
…and the output returned via the snap-in method.
In the case of the Quest tools, there is a Windows PowerShell format file in the directory called Quest.ActiveRoles.ADManagement.Format.ps1xml that contains a different view for the object that is returned by Connect-QADService. You can use Update-FormatData to load this format file into your session, but it is my opinion that this makes loading a snap-in via Import-Module a bit more cumbersome than just loading it with Add-PSSnapin. If your only goal is to avoid having administrator privileges, you could consider it unavoidable. Fortunately for us, there is a much more elegant solution to the problem.
Before we look at the solution to the format problem, I’d like to look at another problem that can occur when using Import-Module to load a snap-in. Let’s take a look at another extremely popular snap-in that does not come from Microsoft: VMWare’s PowerCLI.
We will be using the 4.0 U1 version of PowerCLI because I have not yet installed 4.1. When we load PowerCLI with Import-Module from the directory PowerCLI was installed into, it appears to load without problem:
However, as soon as we start to use the cmdlets, we immediately see that not everything has been loaded properly. This is shown in the following image.
In this case, there are DLLs in the PowerCLI directory that also need to get loaded before you can use this snap-in as a binary module. Though you could load each assembly manually, this soon becomes cumbersome.
The solution? PSD1 files!
Windows PowerShell 2.0 gives us a new file called a PowerShell Definition file (PSD1—also known as a module manifest file). This file type can be used to describe and load all of the appropriate pieces you need for a module. PSD1 files have a FormatsToProcess section in which you can feed it the name of your ps1xml file, a section for RequiredAssemblies where you can enter all of the DLLs you will require, and even a section called TypesToProcess which can load custom types from a ps1xml file.
You can take an existing PSD1 file and modify it to suit your needs. For example, to point the manifest file to your snap-in DLL, add two additional DLLs, and then add a format file, you would make sure the following lines are in your module manifest:
ModuleToProcess = 'ScriptingGuy.snapin.dll' RequiredAssemblies = 'ScriptingGuy1.dll', 'ScriptingGuy2.dll' FormatsToProcess = 'ScriptingGuy.formats.ps1xml'
You will also need to update the GUID property with a valid unique GUID. Fortunately, there’s a much easier way to generate a module manifest file that will do this for you. You can use the New-ModuleManifest cmdlet that comes with Windows PowerShell 2.0:
New-ModuleManifest -Path ScriptingGuy.psd1 -Author ScriptingGuy -CompanyName Microsoft -ModuleVersion 1.0 -Description "The greatest set of cmdlets ever" -FormatsToProcess "ScriptingGuy.formats.ps1xml" -RequiredAssemblies @("ScriptingGuy1.dll","ScriptingGuy2.dll") -NestedModules @() -Copyright "" -ModuleToProcess ''ScriptingGuy.snapin.dll" -TypesToProcess @() -FileList @()
Now you can use the following to load your module:
Import-Module -Name c:\pathtosnapin\ScriptingGuy.psd1
There is one final thing you can do to make your life even easier. If you create a folder within your modules directory that has the same name as your psd1 file, you can copy all of your files into your directory so that you can use Get-Module -ListAvailable and Import-Module modulename as you do with other modules you may have on your computer.
The technique described above is a perfect way to add third-party snap-ins to your corporate module repository. In addition to allowing users to use snap-ins without requiring administrator privileges, a module manifest can also help you control what is provided to your users. For more information about the fields you can use in a manifest file, you should read through the get-help -full for New-ModuleManifest as well as the documentation on MSDN: How to Write a Module Manifest.
Note: PowerCLI will still require administrator privileges in order to install VMWare VIX. This is only needed if you wish to use the cmdlets that interface with VMWare VIX like Invoke-VMScript.
Thank you Tome for being our guest blogger and sharing your knowledge. Tomorrow is guest blogger Oliver Lipkau who will tell us about working with cross forest group memebers.
We invite you to follow us on Twitter and Facebook. If you have any questions, send email to us at firstname.lastname@example.org, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson and Craig Liebendorfer, Scripting Guys