The Shell vs. The Host

One thing that's often very confusing about PowerShell is the difference between the shell itself - what I'll call the engine in this article - and the application that hosts the engine.

You see, you as a human being can't really interact directly with PowerShell's engine. Instead, you need a host application that lets you do so. The standard console - PowerShell.exe - is one such host; the Integrated Script Environment (ISE) is another. Those hosts "spin up" a runspace, which is essentially an instance of the PowerShell engine. When you type a command and hit enter, the host creates a pipeline, jams your command into it, and then deals with the output.

A number of standardized PowerShell commands actually require the host to implement some kind of command support. For example, most of the core Write- cmdlets actually depend upon the host to do something. Write-Verbose is a great example: The command causes the engine to spew text into the Verbose pipeline; the host is responsible for doing something with it. In the case of the console host, the Verbose text is displayed as yellow text (by default) preceded by the word "VERBOSE:".

When you develop a script using the ISE or the console (which behave pretty similarly for most of the core commands), you get used to your script behaving in a certain way. If you then move that script over to another host - perhaps a runbook automation system that runs PowerShell scripts by hosting the engine, rather than by launching PowerShell.exe - you may get entirely different behavior.

Here's a perfect example: most of the "built-in" variables you're used to working with in the ISE or the console aren't actually built into the engine, they're built into those hosts. For example, since the host is responsible for presenting verbose output, the host is what creates and uses the $VerbosePreference variable. When your script is running in a different host, $VerbosePreference may not exist, and indeed verbose output may simply be ignored. An off-the-shelf PowerShell runspace doesn't actually come with very much "built-in" at all, so scripts can behave very differently.

It's pretty important to understand these potential differences. When a developer sets out to create their own host application - like most of the commercial script editors do - it can be very confusing and frustrating, because they essentially have to reverse-engineer much of what the PowerShell.exe console application is doing, so that they can provide an equivalent experience. But you should never assume that a script's behavior under one host will be consistent in all other hosts; test and verify.

About the Author

Don Jones

Don Jones is a Windows PowerShell MVP, author of several Windows PowerShell books (and other IT books), Co-founder and President/CEO of PowerShell.org, PowerShell columnist for Microsoft TechNet Magazine, PowerShell educator, and designer/author of several Windows PowerShell courses (including Microsoft's). Power to the shell!

5 Comments

  1. Great article! Another example of variables built-in to the host are the Exchange specific variables in the Exchange Management Console. If you load the Snapins directly, you don't get those. Very confusing for a lot of folks - glad you wrote this to help clear it up!

    • Actually... no, I don't think the Exchange-specific variables are created by the host application. The EMS isn't a separate host application, I don't believe, although it does rely on more than just what's in the snapins. I know there's a setup script that adds some functions and variables to the global scope.

  2. I have a simmilar write up of this topic in my Blog. Inspired by your book "PowerShell in Depth".
    I allways use a little flow chart to show this separation of PowerShell and the Host.
    Humans are eye-minded. So a picture can say more then 1000 words.
    You can read my article by use of the Google translate button on my page.
    http://www.admin-source.de/BlogDeu/660/unterscheidung-von-powershell-und-dem-powershell-host

    I have set a pinbback link to this article.
    greets Peter

  3. I run into similar issues with the CodePlex project we use for Forefront Identity Manager.

    It hosts PowerShell inside a FIM workflow, so it is a custom host. The main way people find out is when they try to use Write-Host. The other way they find out is when they RTFM and find out that we put a variable into the runspace for them that has all of the FIM workflow details, a pattern I like a lot but I don't think we explain very well in the documentation for the project:
    http://fimpowershellwf.codeplex.com/wikipage?title=Using%20the%20FIM%20Workflow%20Details%20in%20your%20PowerShell%20Script

  4. It is also worth pointing out that when folks complain about the "shell" experience with PowerShell, often the complaints are related to limitations of the "host" e.g. lack of Unicode support, clunky copy/paste support, etc. That is, the limitations are primarily due to the PowerShell.exe host's reliance on the Windows console subsystem which is way long in the tooth and a bit smelly.