A host by any other name still smells as sweet. Now that I’ve thoroughly confused myself, I’ll move on to an oft-confusing topic for many users of PowerShell; PowerShell Hosts.
Over the years, I’ve seen a few posts on this topic. One of my favorites by Don Jones tries to help people understand how PowerShell works. It delves into why PowerShell may seem to behave differently when running from the regular PowerShell window, the PowerShell ISE, or even Visual Studio Code.
It all has to do with how we interact with PowerShell.
PowerShell Host vs. Shell
When I open up PowerShell or the PowerShell ISE, I am not directly interfacing with the PowerShell engine/shell itself. I am opening an application that hosts the PowerShell engine. This application host is what interacts with the PowerShell engine on my behalf and shuffles any commands that I type to the PowerShell engine to be executed.
Clear as mud, no?
Get-Host and $host
I can get more info about the current host by using either the Get-Host cmdlet or the built-in automatic variable $host
.
Here is an example of running Get-Host
with several common application hosts: PowerShell, PowerShell ISE, Visual Studio Code, and remote PowerShell:
Get-Host
Notice that the name changes between each host.
Regular PowerShell → ConsoleHost
PowerShell ISE → Windows PowerShell ISE Host
Visual Studio Code → Visual Studio Code Host
Remote PowerShell → ServerRemoteHost
Each of these different host applications implements the PowerShell engine a bit differently. Some notable differences between hosts are:
Automatic Variables
Automatic variables are defined by the application host. This includes the $host
variable I spoke about a moment ago. This has already been pointed out above with the different names between each host.
Loaded .NET assemblies
The default set of loaded .NET assemblies is different depending on which host you’re using. I’m going to use the following command to demo that:
[System.AppDomain]::CurrentDomain.GetAssemblies()
Since I just want a count, I’ll modify my code to:
( [System.AppDomain]::CurrentDomain.GetAssemblies() ).count
Then, I’ll run it for each of my example hosts.
As you can see there are different assembly counts depending on which host I’m using.
Regular PowerShell → 22
PowerShell ISE → 51
Visual Studio Code → 42
Remote PowerShell → 18
Look at the differences! Be sure to test and verify before writing and implementing any scripts.
Colors
In the case of regular PowerShell and the PowerShell ISE, you can modify the colors via $host.PrivateData
. For a peek into how that works, see my previous blog – Change the PowerShell Colors.
As for Visual Studio Code, there’s no data in $host.PrivateData
to change since it’s all managed by Visual Studio Code itself.
Remote PowerShell host just uses the colors of the host that was used to establish the connection.
Profiles
Each host typically has two additional profiles that can be loaded when you start up the application. I can see the default profile for a given host by using the built-in automatic variable $profile
.
For example, here is what I see in the regular PowerShell console:
$profile
There is a notable exception for the remote PowerShell host (ServerRemoteHost
). This host does not have any $profiles that will execute.
For more info about PowerShell profiles, check out my two other blogs dedicated to the topic – Standardize PowerShell with PowerShell Profiles and PowerShell Profile Load Order.
Wrapping up
Host overload, right? Right.
As I write my PowerShell code, I just need to keep in mind that testing and verifying my scripts against different hosts is important.
Oh, how many times have I written a script in PowerShell ISE only to turn it over to the task scheduler to see it fail? Far too many times. That’s how many.
Test and verify!
Also, happy PowerShelling! If you need help with any cmdlets, we have a nifty list.