Are you using the correct PowerShell version?

Recently, when I was training a group of enterprise admins, a question came up: Why is PowerShell remoting not working on Windows XP? Well, it does! As it turned out, they had downloaded the "wrong" PowerShell version. How come?

When you search for PowerShell V2 downloads, you will find tons of articles and download links. Only some of them point to the correct final "RTM" link. A lot of people are still blogging about "CTP" versions which really were beta versions with limited functionality. Even worse, it turned out that these out-dated PowerShell versions are still up for download from the Microsoft Download center, so when you follow the "wrong" link, you could get the impression that these CTP versions really were official and up-to-date releases.

This was brought up in our PowerShell MVP chat, and as a consequence, we are trying to get the old out-dated downloads offline. At the same time, we were tossing together ideas that help you identify which version you already have and whether it is the correct one. The results of this joined MVP effort I would like to share with you today.

PowerShell Versions - Watch Out!

Basically, there are two kinds of PowerShell: PowerShell V1 which dates back to 2006, and PowerShell V2 which was released in Oct 09. PowerShell V2 is downwards compatible to V1 so all of your V1 stuff still runs, but in addition, V2 has tons of important new features such as Remoting (executing code on other machines), Modules (the "new" Snapins to load more commands), background jobs (executing code in a separate thread asynchronously) and more. So it is an excellent idea to upgrade to V2. Both versions are supported on Windows XP and up. They do not run side-by-side, so you have to install V2 over V1.

One very easy way of distinguishing both versions is to look for a PowerShell variable called $psversiontable. If it is undefined, then you are running V1. If it is there, you have V2. From outside PowerShell, you can also look at a registry key to differentiate between V1 and V2: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine\PowerShellVersion.

Note that PowerShell often was installed as update package so you do not find it in the list of installed software. You have to look at the update packages. Fortunately, though, the final PowerShell V2 can be installed over V1 without having to uninstall V1 first. Only the outdated CTP versions make you find and manually uninstall V1 first. So if you are trying to install V2 on your machine, and it complains about an existing V1, you may well be using the wrong installation package.

Beginning with Windows 7 / Server 2008 R2, you are on the safe side anyway because these OS are the first to ship with PowerShell included, and they always ship with the final version.

CTP PowerShell V2 is WRONG!

The PowerShell team has prereleased V2 a long time before the final version was done and called these preview versions "CTP" (Community Technology Preview). You can still find links to CTP1, CTP2 and CTP3. All of these versions are outdated and should no longer be used unless some other beta software on your machine really requires it. One reason why you should not use CTPs anymore is because they are lacking some functionality such as Remoting on Windows XP. Other reasons are that CTP versions are unsupported, still had some bugs and also some naming changes were made, so scripts created on CTP1 might not run on the final version of PS V2 anymore.

Unfortunately, it is not a trivial task to identify whether you have the final PowerShell V2 or some of the preview versions because - CTP versions have a $psversiontable variable, and the versions reported by it can differ from OS to OS and CTP to CTP. So if you do get back a result from $psversiontable, make sure the BuildVersion is equals or greater than 6.0.6002.18111.

If you want to check your local PowerShell version, you could wrap that logic into a function like this:

function Test-PowerShellVersion {

if (Test-Path variable:psversiontable) {
$versionPresent = $psversiontable.buildversion

if (
($versionPresent.Major -ge 6) -and
($versionPresent.Build -ge 6002) -and
($versionPresent.Revision -ge 18111)
) {
"V2 RTM"
} else {
"V2 CTP Prerelease - Update to V2 RTM!"
}
} else {
"V1 - Update to V2 RTM!"
}
}

It tells you exactly whether you have the final V2 or some outdated prerelease installation. Thanks Max for investigating the version numbers and Shay for tossing in version checking!

Wait a minute - How can I check my enterprise?

Of course, the quick solution I just presented will not help when you need to investigate your entire network. It also helps only when you examine PowerShell from within. What if you have no access to the $psversiontable variale because you are not checking from within a PowerShell script?

As it turns out, the BuildVersion reported by $psversiontable really is the version found in the PowerShell assembly. You could get to it from other programming languages by instantiating a PS object and then looking at the version. This is the route to take for anyone wanting to create an inventory solution based on VB.NET or C#. Here is a PowerShell line that illustrates how to get to the version (thanks Oisin!):

([psobject].assembly.getcustomattributes(
[reflection.assemblyfileversionattribute], $false)
)[0].version

If you just wanted to check computers in your network, you can use a PowerShell script. Since PowerShell V2 Remoting is not available on downlevel installations, in order to get the file version remotely, use WMI. The following script Test-PSVersion represents all I thought was useful and consists of a lot of individual contributions made in our MVP list. So it is by no means my function or accomplishment alone but instead the result of a joined team effort in our MVP group. Special thanks go to Alexander for bringing up the WMI queries and Kirk for perfecting the parameter decoration and reading the OS info via WMI. There were many other MVPs involved. So forgive me if I do not credit everyone.

Should you find errors in this script, they are my fault alone (as I was putting together this specific script ;-) ). In this case, I kindly ask you to leave a comment below. You can download the function here: http://powershell.com/cs/media/p/4591.aspx

function Test-PSVersion {
[CmdletBinding()]
param(
[parameter(Position=0,ValueFromPipeline=$true)]
[ValidateNotNullOrEmpty()]
[String[]]
$ComputerName = @('.'),

[Parameter()]
[ValidateNotNull()]
[System.Management.Automation.Credential()]
$Credential = [System.Management.Automation.PSCredential]::Empty
)
process {

if (Test-Connection -ComputerName $computername -Count 1 -ErrorAction SilentlyContinue) {
try {
$OS = Get-WmiObject -Namespace root\CIMV2 -Class Win32_OperatingSystem `
-ComputerName $computername -Credential $credential -ErrorAction SilentlyContinue
if ($OS) {
$path = "$($OS.SystemDirectory -replace '\\','\\')\\WindowsPowerShell\\v1.0\\powershell.exe"
$OSName = $OS.Name.Split('|')[0]
$query = "SELECT Version FROM CIM_DataFile WHERE Name = '$path'"
$PSEXE = Get-WmiObject -Query $query -ComputerName $computername -Credential $credential
if ($PSEXE.Version) {
$buildversion = $PSEXE.Version.Split()[0]
$versionPresent = [version]$buildversion
$versionRequired
= [version]'6.0.6002.18111'
if ($versionPresent -ge $versionRequired) {
$psversion = "V2 RTM"
} elseif ($versionPresent.Major -ge 6) {
$psversion = "V2 CTP Prerelease - Update to V2 RTM!"
} else {
$psversion = "V1"
}

New-Object PSObject -Property @{
ComputerName=$OS.__SERVER;
BuildVersion=[version]$buildversion
Version=$psversion;
Status=$true;Description='OK';
OSName = $OSName

}
} else {
New-Object PSObject -Property @{
ComputerName=$computername[0];
BuildVersion=[version]$null;
Version='n/a';
Status=$false;
Description='Unable to access OS information via WMI.';
OSName = 'n/a'
}
}
}
}
catch {
New-Object PSObject -Property @{
ComputerName=$computername[0];
BuildVersion=[version]$null;
Version='n/a';
Status=$false;
Description=($_.Exception.Message);
OSName='n/a'
}
continue
}

} else {
New-Object PSObject -Property @{
ComputerName=$computername[0];
BuildVersion=[version]$null;
Version='n/a';
Status=$false;
Description='Computer did not respond to ping, skipped.';
OSName='n/a'
}
}
}
}

"localhost", "pc77", "localhost", "storage1" |
Test-PSVersion

You can call this script over the pipeline and pipe a list of computers into it, or you can call Get-Content and read in the content of a list of computernames and pipe the result to Test-PSVersion. What you should get in return should look similar to this:

Version : V2 RTM
OSName : Microsoft Windows 7 Ultimate
Status : True
ComputerName : DEMO5
Description : OK
BuildVersion : 6.1.7600.16385

Version : n/a
OSName : n/a
Status : False
ComputerName : pc77
Description : Computer did not respond to ping, skipped.
BuildVersion :

Version : V2 RTM
OSName : Microsoft Windows 7 Ultimate
Status : True
ComputerName : DEMO5
Description : OK
BuildVersion : 6.1.7600.16385

Version : V2 RTM
OSName : Microsoft Windows Server 2003 for Small Business Server
Status : True
ComputerName : STORAGE1
Description : OK
BuildVersion : 6.0.6002.18139

Conclusion

It is time to check your PowerShell version! Make sure you are not using any prerelease software (unless you need to for obscure reasons). And if you find yourself using PS V1, consider an upgrade. It is free and worth it!

I hope on behalf of all of us PowerShell MVPs, with the code and examples in this post, we provided you with the inventory tools you need to make this happen. To get your hands on PowerSjell V2 RTM, there are (too) many dowload pages. To download PowerShell V2 and learn all about prerequisites etc. I found this link up-to-date and useful: http://support.microsoft.com/kb/968929

Have fun! Hey, have you tried the latest release of PowerShell Plus? It's free!

And one more thing: if you happen to be located in Germany, Switzerland or Austria, rent me!

I am doing inhouse trainings, tutorials and projects. Simply drop a mail to tobias@powershell.com, and maybe we meet in person some time soon...! I have tons of tricks for you and do trainings for midsize and large enterprises on a regular basis - it's always a lot of fun!

Cheers

Tobias


Posted Jan 20 2010, 05:50 PM by Tobias

Comments

Xenophane wrote re: Are you using the correct PowerShell version?
on 01-25-2010 6:40 AM

May I suggest that you put in a test to see if you are running against Server 2008 R2 or Windows 7 ?

Since the revision number in Win 7 and R2  is 16385 and you check for revision number 18111 or higher, you will end up with Win 7/R2 machines showing up as having a CTP release, and recommend you to upgrade.

I could imagine there are people out there, who might not read all the text, and will just run the code against a machine running Win7 or R2 and think they will need to upgrade.

Tobias wrote re: Are you using the correct PowerShell version?
on 01-25-2010 7:15 AM

Xenophane, you were right. There were actually two bugs, so the script did return the correct BuildVersion but the wrong clear-text version. I have corrected this now. Can you check on W7/S2008R2 to make sure? Thx!

Tobias wrote re: Are you using the correct PowerShell version?
on 01-25-2010 7:39 AM

for the records, simplified the version check by comparing [version] types instead of individual version subproperties, added OSName to show the kind of OS found on the system examined.

Xenophane wrote re: Are you using the correct PowerShell version?
on 01-25-2010 1:51 PM

That seems to work, tested it for both Win 7 and Server 2008 R2, very nice solution             :)

Then I wont spend anymore time on my own version  :)

dpurrington wrote re: Are you using the correct PowerShell version?
on 01-26-2010 11:48 AM

Really useful info, I wanted to point out a problem with the first script.

"make sure the BuildVersion is equals or greater than 6.0.6002.18111."

The Test-PowerShellVersion function is not quite right because builds beyond 6002 are not detected as V2 RTM. For example, on Win 2k8 R2, the version info is 6.1.7600.16385. A corrected version:

function Test-PowerShellVersion {

if (Test-Path variable:psversiontable) {

$versionPresent = $psversiontable.buildversion

if (($versionPresent.Major -eq 6) -and

(($versionPresent.Build -gt 6002) -or

(($versionPresent.Build -eq 6002) -and ($versionPresent.Revision -ge 18111))

)) {

"V2 RTM"

} else {

if ($versionPresent.Major -gt 6) {

"You are from the future. I demand to see your time machine."

} else {

"V2 CTP Prerelease - Update to V2 RTM!"

}

}

} else {

"V1 - Update to V2 RTM!"

}

}

cmille19 wrote re: Are you using the correct PowerShell version?
on 01-29-2010 7:32 AM

Pingback from chadwickmiller.spaces.live.com/.../cns!EA42395138308430!843.trak

Deck Hazen wrote re: Are you using the correct PowerShell version?
on 04-15-2010 5:15 PM

90 lines of code to do a simple "ver" command?  Get real.

jboxter wrote re: Are you using the correct PowerShell version?
on 12-08-2010 9:58 PM

this version is working extremely well on both my windows and MAC machines. I did have a question about the third line of code. I am having trouble implementing this on my cloud computing datacenter. Any help?

Pollen wrote re: Are you using the correct PowerShell version?
on 01-12-2011 10:58 AM

Oh many, so that's why powershell didn't work on my previous PC. How was I supposed to know that? Anyway, I can't wait to try it again now that I do know that it probably was the wrong version.

Copyright 2012 PowerShell.com. All rights reserved.