Tag Archives: $PSVersionTable

Run One from the Other

It wasn’t but a few days ago that I saw something that piqued my interest. It was an example of running a command against PowerShell Core (pwsh.exe) from Windows PowerShell (powershell.exe), or maybe it was the other way around? Whichever, I’ve included an image that shows this working in both directions. That’s to say it’s an example of running the same command in both versions of PowerShell, from each version of PowerShell.

I do suspect the picture will help explain things, if that last paragraph didn’t.

In the above image, we can see that we’ve run a command against both Windows PowerShell (5.1) and PowerShell Core (6.1). In both consoles, we’ve run the same command; it’s included below. Its goal was to return the version of PowerShell, for both versions of PowerShell.

'powershell.exe','pwsh.exe' | ForEach-Object {
    & $_ -Command {$PSVersionTable.PSVersion}
}

Our results are identical; we knew, we were running 5.1 and 6.1. Neat, right!? Keep this trick in your back pocket, as I do suspect it may be helpful for one of us, one day. Maybe it won’t have anything to do with obtaining the version, of a version of PowerShell, and instead someone will find another use.

Here’s a start. The thought I had was, can I run an Active Directory command in Windows PowerShell (powershell.exe) from PowerShell Core (pwsh.exe)? You bet I can.

In the below example, I’ve returned my GivenName from Active Directory using Windows PowerShell, from PowerShell Core. That could be potentially helpful for someone in some yet-to-be-thought-of project.

Especially in the case of Active Directory, it’s important to remember that each time a command is run, it must import the Active Directory module. Consider that each command is spinning up a new powershell.exe process. For all we know, this may be the reason why the WindowsCompatibility module uses PowerShell sessions, and not PowerShell processes.

In this next example, we issue a Windows PowerShell only command that’s tied to a builtin Microsoft Windows PowerShell model. We issue the Get-LocalUser cmdlet out of the Microsoft.PowerShell.LocalAccounts module. While it’s still importing a module into a powershell.exe process, it loads quicker than the ActiveDirectory PowerShell module did.

I’m going to need to call this a night here soon, but I keep finding more things to try. Like this example. There’s two commands. The first one runs Windows PowerShell, which runs PowerShell Core to determine the version of PowerShell Core.

The second one runs Windows PowerShell, which runs PowerShell Core, which runs Windows PowerShell to determine the version of Windows PowerShell. The image for these examples might be easier to understand, too.

Alright, that’s it for now. Perhaps I’ll come up with some other ideas to try another day. I need to put this post, and me, to bed.

Get the Version of PowerShell (Not its Host)

I’ve seen it over and over again: people telling people to use $Host, or the Get-Host cmdlet, to determine the version of Windows PowerShell. Please stop. Get-Host and $Host return a version, sure, but that’s the version of the host – the application that is hosting PowerShell. It’s not the version of PowerShell.

For many of us, the host is the PowerShell console, or the ISE. The name of the console host is ConsoleHost, and the name of the ISE host is ‘Windows PowerShell ISE Host.’ You can return these names by entering $Host or Get-Host, in the respective host, and looking at the Name property. These hosting applications are made by our friends at Microsoft, and so often, if not always, the version of the host will match the version of PowerShell. That said, you’d still be better served to get your results from the proper variable, especially in certain situations.

In order to ensure you are returning the version of PowerShell, use the automatic variable $PSVersionTable. The examples below show how to return information using this variable. Notice how we further isolate the version property – a suitable thing to do when you’re using the correct variable.

PS C:\> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      4.0
WSManStackVersion              3.0
SerializationVersion           1.1.0.1
CLRVersion                     4.0.30319.34014
BuildVersion                   6.3.9600.17090
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0}
PSRemotingProtocolVersion      2.2

PS C:\> $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
4      0      -1     -1

PS C:\> $PSVersionTable.PSVersion.Major
4
PS C:\>

We can do the same type of property isolation with $Host and Get-Host. However, to get in this habit while using $Host, or Get-Host, is a bad idea, and may lead to wasted time and confusion if you’re attempting to determine the version of PowerShell.

PS C:\> $Host

Name             : ConsoleHost
Version          : 4.0
InstanceId       : 48ae3046-45ed-46d4-bf6a-0b7e289856db
UI               : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture   : en-US
CurrentUICulture : en-US
PrivateData      : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
IsRunspacePushed : False
Runspace         : System.Management.Automation.Runspaces.LocalRunspace

PS C:\> $Host.Version

Major  Minor  Build  Revision
-----  -----  -----  --------
4      0      -1     -1

PS C:\> $Host.Version.Major
4
PS C:\>

The problem occurs when we’re using other hosting applications and under the belief $Host, or Get-Host, returns the version of PowerShell. The first instance that comes to mind, where we can see this problem, is when you’re using PSRemoting. If you’re not using the $PSVersionTable variable in a remote session, then you’re likely going to end up with incorrect results, when you try and get the version of PowerShell.

The example below uses an interactive session on a remote computer. $Host says we’re using version 1, but again, it’s reporting the version of the host (this time it’s named ServerRemoteHost). $PSVersionTable correctly indicates we’re using PowerShell 4.0. I’ve also returned the version of the operating system. Microsoft Server 2012 R2, by default, comes with PowerShell 4.0.

PS C:\> Enter-PSSession -ComputerName dc01
[dc01]: PS C:\Users\tommymaynard\Documents> Set-Location \
[dc01]: PS C:\> $Host.Version

Major  Minor  Build  Revision
-----  -----  -----  --------
1      0      0      0

[dc01]: PS C:\> $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
4      0      -1     -1

[dc01]: PS C:\> $Host

Name             : ServerRemoteHost
Version          : 1.0.0.0
InstanceId       : aed243b7-73ee-45c8-9032-2f2a5679f6ed
UI               : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture   : en-US
CurrentUICulture : en-US
PrivateData      :
IsRunspacePushed :
Runspace         : System.Management.Automation.Runspaces.LocalRunspace

[dc01]: PS C:\> (Get-CimInstance -ClassName Win32_OperatingSystem).Caption
Microsoft Windows Server 2012 R2 Standard
[dc01]: PS C:\> Exit-PSSession
PS C:\>

Use $PSVersionTable to make sure you capture the proper version of PowerShell – not the version of the host, that’s hosting PowerShell. If this is one of your bad habits, then change it now, before you wish you had.

Change the Console Window Title – Part 1

This post will introduce the $Host automatic variable, its properties, and how we can use it to display the date in the Window PowerShell console’s window title.

The $Host variable is an automatic variable and an automatic variable in Windows PowerShell stores “state information” about the PowerShell session. These types of variables are created and maintained by PowerShell. The example below shows the properties of the $Host automatic variable. We can return this same information by also using the Get-Host cmdlet, as seen in the second example.

PS C:\> $Host

Name             : ConsoleHost
Version          : 3.0
InstanceId       : 30d047c2-0565-4947-8f34-7ff2b42d3590
UI               : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture   : en-US
CurrentUICulture : en-US
PrivateData      : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
IsRunspacePushed : False
Runspace         : System.Management.Automation.Runspaces.LocalRunspace

PS C:\> Get-Host

Name             : ConsoleHost
Version          : 3.0
InstanceId       : 30d047c2-0565-4947-8f34-7ff2b42d3590
UI               : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture   : en-US
CurrentUICulture : en-US
PrivateData      : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
IsRunspacePushed : False
Runspace         : System.Management.Automation.Runspaces.LocalRunspace

Note: Please not use the $Host variable, or the Get-Host cmdlet, to determine the installed version of Windows PowerShell. This variable does not return the version of Windows PowerShell; it returns the version of the host. To determine the version of Windows PowerShell use the $PSVersionTable variable and the PSVersion property.

The UI property in the previous examples has several words separated by dots. This means that the UI property is actually a collection. In most cases, a collection stores a collection of properties. The example below shows how to enumerate the UI property so we can see the properties contained in this collection.

PS PS C:\> $Host.UI

RawUI
-----
System.Management.Automation.Internal.Host.InternalHostRawUserInterface

Wait, what? The UI collection contained RawUI – another collection. After further enumeration, this collection returns several properties. At the bottom of property list is, a property called, “WindowTitle.” This property stores the value used in the window title of the PowerShell console.

PS C:\> $Host.UI.RawUI

ForegroundColor       : DarkYellow
BackgroundColor       : DarkMagenta
CursorPosition        : 0,1
WindowPosition        : 0,0
CursorSize            : 25
BufferSize            : 120,3000
WindowSize            : 120,50
MaxWindowSize         : 120,85
MaxPhysicalWindowSize : 240,85
KeyAvailable          : False
WindowTitle           : Administrator: Windows PowerShell

In the image below, the window title accurately matches what is stored in this property.

Windows PowerShell Console Window Title 05 - Part 1

The title can be changed by assigning a different value to the property $Host.UI.RawUI.WindowTitle. In this example, the window title changes instantly when we assign a new value to the property.

PS C:\> $Host.UI.RawUI.WindowTitle = 'The new and improved title!'
PS C:\>

Windows PowerShell Console Window Title 06 - Part 1

Our goal is to keep the default value, Administrator: Windows PowerShell, append a space, and then the date, inside square brackets. We want it to look like this, “Administrator: Windows PowerShell: [06/19/2014].” To reset the value to its default, close the current PowerShell console and then open a new PowerShell console. Think about that for a moment… This value is going to reset itself to the default value every time a new PowerShell session is created, such as when a new console window is opened. We will discuss this more in a moment.

In the next two examples, the value of $Host.UI.RawUI.WindowTitle is changed by concatenating the date, the space, and those brackets, to the already existing value of this property. Notice that we do this using the += assignment operator. These two examples do the exact same thing.

PS> $Date = Get-Date
PS> $Host.UI.RawUI.WindowTitle += " [$Date]"
PS>

Windows PowerShell Console Window Title 07 - Part 1

PS C:\> $Host.UI.RawUI.WindowTitle += " [$(Get-Date)]"
PS C:\>

Windows PowerShell Console Window Title 08 - Part 1

The time indicates the time in which the PowerShell session started – pretty useless. Using the ToShortDateString method returns the date without the time. Both of the next two examples do the same thing.

PS C:\> $Date = (Get-Date).ToShortDateString()
PS C:\> $Host.UI.RawUI.WindowTitle += " [$Date]"
PS C:\>
PS C:\> $Host.UI.RawUI.WindowTitle += " [$((Get-Date).ToShortDateString())]"
PS C:\>

Windows PowerShell Console Window Title 09 - Part 1

As I mentioned previously, the value that is stored in $Host.UI.RawUI.WindowTitle returns to its default each time a new Windows PowerShell session is opened. In order for this to stick, it needs to be added to a profile. A profile runs each time you start a new PowerShell session. If you’re not already using a profile, then it’s time to begin. Start by reading this article: http://technet.microsoft.com/en-us/library/ee692764.aspx and then follow that up by reading the help file: Get-Help about_Profiles.

Edit: You can also read the recently added Help Rewrite for about_Profiles here: http://tommymaynard.com/hr-about_profiles/

PS C:\> Get-Help about_Profiles

That is all there is to change the Windows PowerShell console’s window title to the current date. Watch for an upcoming post that will help determine how to update the date if the Windows PowerShell session is open for more than one day.