Slow tab expansion in Ops Mgr Powershell V2 console

I am a big Powershell fan, and I use the Powershell console regularly.  Depending on what I’m taking care of at the time, I might be using the plain vanilla console or I might be using the Operations Manager snapin to work with the latest builds of our product.  In both contexts, I find that a tab expansion feature makes my life a lot easier.  Powershell V1 had tab expansion support, and with Powershell V2 the tabbing capabilities have been greatly enhanced.<?xml:namespace prefix = o ns = “urn:schemas-microsoft-com:office:office” />

One bad thing I found with V2 tab expansion is that it is SLOOOW to autocomplete cmdlet names when using the Operations Manager snapin.   Typing something like “Get-Aler[TAB]” or even a standard cmdlet like “Select-Stri[TAB]” would sometimes hang your console for minutes.  This came up on the SCOM newsgroup recently, so it is clearly a problem for a fair number of folks.

So what’s the root cause of this?

In certain cases, when you try to tab expand, Powershell attempts to autocomplete to the name of an object in the current prompt location.  For example, if navigate to C:WindowsSystem32 and type “user32[TAB]”, Powershell autocompletes to “.user32.dll” as expected.  This isn’t anything new for cmd.exe users, but what’s cool is that this behavior can be enabled by any Powershell provider, so it isn’t limited to the file system.  Try moving to HKLM:SOFTWARE, typing “microso[TAB]”, and the Powershell Registry Provider supplies the information which allows this to autocomplete out to “.Microsoft”.  Very smooth, consistent experience.

Everything works really fast for providers like the file system and the registry, but things can sometimes take (much) longer with the Operations Manger provider.  To enable tab expanding the names of Groups and Monitoring Objects in the Ops Mgr provider, behind the scenes a few queries need to be sent all the way to the ops DB, results collected, and .NET objects built and sent back over the wire to your session.  This is what’s bogging down your prompt, especially if you are on a remote machine.

The fix is to tweak the TabExpansion function in V2 so that it doesn’t try to autocomplete child objects if using the Ops Mgr provider.  This can be done via the below script.  Paste this into your console session, or better yet add it to your profile, and tab expansion for Ops Mgr cmdlets will work much more quickly.

$tabExpand = (get-item function:tabexpansion).Definition
if($tabExpand -match ‘try {Resolve-Path.{49}(?=;)’)
{
   $tabExpand = $tabExpand.Replace($matches[0], “if((get-location).Provider.Name -ne ‘OperationsManagerMonitoring’){ $($matches[0]) }” )
   invoke-expression “function TabExpansion{$tabExpand}”
}

Note this only works for Powershell V2, and only if you have not already modified that line of the TabExpansion function.  In Powershell V1 more of the tab completion is handled in the engine so unfortunately a similar speedup is not possible in this case.

Trying it out:

PS># How long does it take to tab expand “get-manage[TAB]”
PS># before…
PS>measure-command {TabExpansion ‘get-manage’ ‘get-manage’ } | select TotalSeconds


TotalSeconds      : 9.6371766

PS># after…
PS>measure-command {TabExpansion ‘get-manage’ ‘get-manage’ } | select TotalSeconds


TotalSeconds      : 0.0091002

 

I’ll take a 1,000x speedup any day!

-Lincoln Atkinson