Essential PowerShell: Use non-portable console customizations sparingly
Isn’t it odd how issues with software are often raised in groups? I’ve been helping people use software for a long time and I find it uncanny how when I come across an issue once, there are bound to be two or three other occurrences of the same issue just about to be brought to my attention. Maybe it just seems that way because once I’m on track to discovering the issue I notice other occurrences of the same issue more easily. All I know is that this happens all the time.
Recently one such issue came to my attention quite a few times and it needs to be talked about. Any of the following questions were used by those facing the issue:
- Why doesn’t this command work in that PowerShell console?
- Why did my PowerShell script work when I ran it here but it doesn’t work when I run it there?
- Why can’t I find command commandName? It worked fine when I used it in the other console.
- I used to be able to use drive driveName, but I can’t anymore. Why?
The answer to these questions lies in the recognition of one area where PowerShell is not very consistent: through the use of customized PowerShell consoles.
Since PowerShell has been out now for over a year, many product teams now provide PowerShell snapins for their products. This includes Microsoft products like Exchange, System Center Operations Manager, System Center Virtual Machine Manager, SQL Server and IIS (among others) as well as ISV products like VMware ESX and Server (the VI toolkit) and Quest ActiveRoles Server (the QAD cmdlets). And there are others who provide PowerShell snapins for a particular business need, like SDM Software’s Group Policy Management Console (GPMC) Cmdlets, /n software’s NetCmdlets, and SoftwareFx’s PowerGadgets. Many (the majority, in fact) of these snapins come with their own customized PowerShell console. These customized console are designed to do one or more of the following:
- Display welcome text with help.
- Show a tip of the day.
- Run in elevated mode on Windows Vista and Windows Server 2008.
- Load the PowerShell snapin(s) relevant to the product that the shell customization came with.
- Change the current location to a provider that was included with the snapin(s) or a drive that was created within the customized shell.
- Create custom commands (functions and aliases) to make it easier to use the snapin(s).
- Prompt the user for connection-related information to establish a connection required for the cmdlets to work.
There are definitely other possibilities of how these customized consoles might be used, but this list gives you the general idea. Most of these customizations are helpful because it gives the PowerShell newcomer a starting point; however, more than half of them can give users the wrong impression and cause them to ask the questions listed above when they use other PowerShell consoles. Let’s look at some examples.
One thing in common among each of the customized consoles is that they load the PowerShell snapin(s) relevant to the product that the shell customization came with. The Exchange Management Shell loads the two snapins that come with Exchange, so that users don’t have to do this to use Exchange cmdlets:
Add-PSSnapin -Name `
Add-PSSnapin -Name `
This might not seem like a big issue, however in practice it seems to give users the false impression that they can simply call the cmdlets they need from any PowerShell script or console, which ultimately results in head-scratching when commands or a script don’t work somewhere else. And as indicated, this is common among each of the customized consoles, so the IIS PowerShell Management Console, System Center Operations Manager Command Shell, Windows PowerShell with PowerGadgets, and others all do the same thing, loading their respective snapin automatically.
Another customization that seems to be common is for consoles to provide custom commands (aliases and functions) that are only available in that particular console. VMware does this in their VMware VI Toolkit (for Windows). When you open that console, you are presented with a message that shows you four commands as useful starting points, three of which only work in the VMware VI Toolkit (for Windows) shell (FYI, the commands I’m referring to are Get-VICommand, Get-VC and Get-ESX). You can imagine that causes confusion when someone is trying to use one of these commands in another console. Of course VMware isn’t the only one that does this. The Exchange Management Shell creates three commands that are only available by default in that console (Get-ExCommand, quickref and Get-ExBlog) and the System Center Operations Manager Command Shell creates 10 commands that are only available by default in that console. I won’t bother listing all of those here because I’m sure you get the picture by now. Trying to use these commands in other consoles without adding them to the profile or explicitly creating them results in an error indicating that the command was not found and invariably some head scratching for the individual who is trying to run then.
A third type of customization is to check for the presence of a connection and then to prompt users for connection information if a local connection was not detected. The System Center Operations Manager 2007 Command Shell provides connection management like this in its console. The connection that is established is not usable outside of that console, nor is it documented accordingly, so users need to be aware that their scripts will have to include commands to make the required connections in order to work in any PowerShell environment.
There are surely going to be other examples of this as different teams customize their console environment to meet their needs. As a PowerShell end user, when these customized consoles are very convenient, what can we do to make sure we’re aware of what customizations are being made?
Fortunately the console customizations are easy to discover. Every customized console uses PowerShell’s command line parameters to perform the customizations. This means viewing the properties of any of the shortcuts used to launch a customized console allows you to see what customizations are being performed by examining the command line parameters for powershell.exe. The customizations that you need to look at are the PowerShell console file that is used (as identified by the -psconsolefile argument) and the script that is executed (as identified by the -command argument). The PowerShell console file (psc1 file) is an xml document that defines which snapins should be automatically loaded by PowerShell when it starts. The snapins identified in this file are silently added to the PowerShell session when it is opened. The command argument identifies the PowerShell script or PS1 file that will be run after the snapins are loaded. This script is used to customize the look of the console, create custom commands, manage connections, etc.
Now that you have this information, all you need to do is make sure you are aware of the customizations in the console you are using, particularly those that are not portable to other consoles, so that you don’t make incorrect assumptions when you write your scripts.
Before I close this off, I have a request that I’d like to put out there for snapin developers. If you’re creating a customized PowerShell console when your snapin is installed, please make an effort to make those customizations self documenting. I don’t want you to hurt the end user experience your after, but I think a bit of carefully worded output that identifies your console customizations as customizations that are specific to that console would go a long way to educate beginner PowerShell users about how consoles can be customized and what they need to be aware of when switching from one console to the next. Without that information, users simply aren’t getting the information that they need to use your commands in other console that they might use. And of course, if you are making custom function that are only available in your customized console, ask yourself, should those function only be available in one console, or should they be available all the time. Often times I bet the answer is the latter, so please consider making cmdlets for those function you feel are necessary for the right experience when using your snapin. Otherwise you’re just making it more difficult for your users to have the experience that you want them to have.
Thanks for reading!
PS C:> Poshoholic, Microsoft MVP, Technical Product Manager
© 2012 Kirk Munro