Is PowerShell $ShellId too big a burden?

As you may know, I was one of the first developers who jumped on board and started working on an alternative PowerShell host (actually, I’m also the first to create a WPF-based host, and the first to create one that was open source … but enough about me).

Recently I’ve picked back up on that project, and am just about ready to release what I hope will be the last “pre-release” of PoshConsole before I declare it to be “beta” quality and start doing more regular releases. ;-)

Trivial example of inline WPF outputThe coolest features of PoshConsole, the ones that are really revolutionary, involve exposing the WPF surface to scripts and cmdlets so that you can actually have graphical output in the console — not popups, and not just for fun… but stuff like putting bar graphs behind the size columns in Get-ChildItem for folders, and the memory columns in Get-Process, etc… anyway.

So I’ve been writing a few scripts to show off the possibilities of PoshConsole, and was thinking about even posting them on the PoshCode.org PowerShell Script Repository, but I wanted a way to make clear that they’d only work in PoshConsole.

A little investigation later, and it was clear that PowerShell has a built in feature for this: #requires -ShellId PoshConsole … except, it doesn’t work. Actually, it doesn’t work for two reasons:

  1. PowerShell always ignores #requires -ShellId Anything
  1. No other PowerShell host implements ShellId as far as I can see

The ShellId is a read-only property of the RunspaceConfiguration, so to implement it in your PowerShell host you have to create your own RunspaceConfiguration class inheriting from the abstract base class. The problem is, there are some expensive side-effects:

  1. You have to configure the available .net Assemblies, Cmdlets, Format files, Initialization Scripts, Providers, Scripts, and Type files …
  2. Having your own ShellId means you don’t inherit anything from PowerShell.exe (like for instance, the ExecutionPolicy)
  1. Some cmdlets just don’t seem to work (Add-PSSnapin is just failing on me with “Object reference not set to an instance of an object”)

So … to sum up: PowerShell ignores #require -ShellId, and I can’t find another host (including Microsoft’s “Graphical PowerShell” and the latest and greatest PowerShell Plus Professional) that bothers to set the ShellId. Can anyone tell me a reason why I should bother with this?

Oh, and, can anyone give me some information about why Add-PSSnapin might be failing when I do set the ShellId?

[new] ShellId IS too big a burden.

After further investigation, it turns out that the reason Add-PSSnapin fails is because it uses a method AddPsSnapIn which is part of the RunspaceConfiguration (that you had to create yourself to set the ShellId), and you can’t implement that method (in fact, you can’t seem to override it with “new” either, I’ll have to look into that a little more).

In any case, the method has to return a PSSnapInInfo object, and since there are no public constructors for PSSnapinInfo objects, you’re sore-out-of-luck. It appears you would literally have to reverse engineer the whole “PSSnapin” system and create your own cmdlets and functionality around it to try to keep your host compatible with the main PowerShell. No wonder nobody’s done this…

I guess I’ll just go back to using Microsoft.PowerShell as my ShellId, I don’t know what I was thinking.

Similar Posts:

6 thoughts on “Is PowerShell $ShellId too big a burden?”

  1. I want!

    Perhaps a global variable signifying that your shell is capable of graphics in the shell output is a reasonable workaround? It would mean that each Cmdlet would need to check for it.

  2. I know there are a few ways to determine which host I’m running in, and I’ve even created a sort-of “standard” for checking if the Host has WPF capabilities: if($Host.PrivateData.XamlUI) … so that hypothetically other people could write Hosts that could support these cmdlets.

    I could even throw my own errors to make it look roughly the same as a #requires statement would look.

    The thing is, there’s a built-in mechanism for handling requirements like this … and I can’t make it work! (And that’s driving my crazy).

    Of course, on top of the “it should be easy” argument (which seems to indicate that this system is designed wrong) ... we’ve been discussing the ability to filter search results on PoshCode.org based on requirements, which would work if we could parse for #requires statements, but wouldn’t have any way of knowing that an if() statement was actually a requirement instead of just a logic branch — so I’d really like the #requires system to work ;-)

  3. @Chad Well, that’s interesting (and now you know why it doesn’t support Add-PSSnapin). I’m going to check if Add-Module behaves the same way. If it doesn’t, maybe I’ll just officially deprecate PSSnapins in PoshConsole.

    By the way, (I posted this in your WorkItem too) depending on what other PowerShell hosts you use, you might want to move the loading of the PSCX profile stuff into a separate script which gets called from Microsoft.PowerShell_profile.ps1 (and/or other host-specific profile scripts). That way it wouldn’t get loaded by the SQLPS (Profile.ps1 is supposed to be host-agnostic). I must admit though, a host that doesn’t do snapins feels a little pointless to me ;-)

  4. It does seem a little pointless, but if you want to launch PowerShell from within SQL Server its your only option. I prefer to use SQL Server PowerShell Extensions (http://www.codeplex.com/sqlpsx) in regular PowerShell when possible, but as a project developer I’m a little bias :)

    Thanks for the insight into shellid and the advice to use Microsoft.PowerShell_profile.ps1 which seems cleaner than the “if ($Shellid -ne ‘Microsoft.SqlServer.Management.PowerShell.sqlps’)” approach I had taken especially since Microsoft is releasing mini-shells like sqlps.exe.

Comments are closed.