January 5th, 2009

Hey, Scripting Guy! How Do I Check Which Version of Windows PowerShell I'm Using?

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! With the release of the Community Technology Preview (CTP) 3 for Windows PowerShell, some of our staff have gone ahead and updated their computers. I am now beginning to worry that I need to check the version of Windows PowerShell that is installed on a computer before I run a script. I have two questions, the first of which is obvious: How do I do this. The second question is this: What the heck is a CTP anyway?

– WS

SpacerHey, Scripting Guy! Answer

Hi WS,

Let’s answer the second question first. What is a CTP? In the old days, when you were writing your computer program (probably poking holes in key punch cards—I still have some lying around), you would first analyze the requirements for the application, do some flow-charting to determine the inputs and the outputs, and then come up with a mock-up. After the customer gave you the go-ahead, you would develop a working prototype. We typically would refer to these things as an alpha. We could continue to refine the product, work on things, and as we were working on the code many times we would realize that things maybe were not working the way we had envisioned that they would work. After we had things working pretty well, we would again show it to the customer. This is a beta. Now we need to fix bugs. So we work real hard fixing the bugs. When we have things working well, we call that a release candidate. Sometimes we go through several release candidates before we actually release the product.

The problem with that approach was the long lead time between the pre-beta product, and the short lead time between the beta product and the released product. In other words, when a product hits beta, its features are pretty much set. So getting input from a customer during the beta phase is good for finding bugs, but it is bad for finding out if what you are making is actually what the customer wants. To resolve this situation, several groups at Microsoft came up with the idea of the community technology preview(CTP), which allows for earlier feedback from the community to the product group doing the coding. Windows PowerShell 1.0 went through a CTP, and it worked out great. Windows PowerShell 2.0 is once again going through a CTP, and many changes to the product have been directly attributed to feature requests coming from our customers. So you can think of a CTP as not being feature complete or bug free. You can think of a beta as pretty much being feature complete, but not bug free. A release candidate is feature complete, and mostly bug free. When working with a release candidate, what you see is pretty much what you will get when the software finally ships.

If you want to identify the version of Windows PowerShell that is running on your computer, you can read the RuntimeVersion value from the registry. This registry key is seen here:

Image of the RuntimeVersion registry key

 

One way to read from the registry is to use the registry provider from within Windows PowerShell and read a registry value as you might read a property from a file or a folder. To do this you need to use the HKLM PS drive—HKLM: in this case—and follow it with the path to the registry key, which is \SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine. You can then select the item property you are interested in, which is RunTimeVersion in this example. This is seen in this script:

$path = "HKLM:\SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine"
$psv = get-itemproperty -path $path
$psv.RunTimeVersion

People who are familiar with VBScript may wish to create the WshShell object and use the RegRead method. To do this we use the HKLM moniker as a shortcut to refer to the HKEY_LOCAL_MACHINE registry key. The HKLM moniker when used with the WshShell object is case sensitive.

We store the path to the Windows PowerShell configuration information in the $path variable. Next we use the New-Object cmdlet to create an instance of the WshShell object. This COM object has the program ID of Wscript.Shell. We store the returned object in the $wshShell variable. After we have the WshShell object, we use the RegRead method to read the registry key value, which we specify by placing the path and value name in an expanding string: “$path\RunTimeVersion”. This script is shown here:

$path = "HKLM\SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine"
$WshShell = New-Object -ComObject Wscript.Shell
$WshShell.RegRead("$path\RunTimeVersion")

There may be times when you wish to use WMI to read the registry. To use WMI to read the registry, we need to use the stdRegProv WMI class. The stdRegProv WMI class has always been in the root\default WMI namespace. Beginning with Windows Vista, we also have an instance of the stdRegProv WMI class in the root\cimv2 (which incidentally really is the default namespace). What this means is that you can use the stdRegProv WMI class from either the root\default WMI namespace or from the root\cimv2 WMI namespace. It does not matter as it is the same WMI class. As a best practice, I recommend that you use the instance of the class from the root\default WMI namespace (as is done in the GetPsVersionWmi.Ps1 script below) to ensure compatibility with older versions of the Microsoft Windows operating system. WMI uses coded values to determine the registry tree (also known as a hive). These coded values are seen in the table just below. HKEY_DYN_DATA registry tree only exists on Windows 95 and Windows 98.

Table 1 WMI registry tree values

Name Value

HKEY_CLASSES_ROOT

2147483648

HKEY_CURRENT_USER

2147483649

HKEY_LOCAL_MACHINE

2147483650

HKEY_USERS

2147483651

HKEY_CURRENT_CONFIG

2147483653

HKEY_DYN_DATA

2147483654

We use the value 2147483650 and assign it to the $HKLM variable. This value points the WMI query to the HKEY_LOCAL_MACHINE registry tree. We then assign the string software\Microsoft\PowerShell\1\PowerShellEngine to the variable $key. When using WMI to read the registry, the key is not preceded with a backslash.

We assign the registry property value we wish to read to the $value variable. Now we use the [wmiclass] type accelerator to obtain an instance of the stdRegProv WMI class. We specify the root\default WMI namespace to specify which version of the stdRegProv WMI class we wish to use. We could also have preceded the namespace with the name of a computer and read the registry from a remote computer. After we have created an instance of the stdregProv WMI class, we use the resulting System.Management.Managementclass to call the GetStringvalue method. The GetStringValue method takes three arguments: the registry key coded value, the registry subkey string, and the property name. Two values are returned by the method call. The first returned value is the returnvalue, which will indicate the success or the failure of the method call; the second is the svalue, which is the string value that was stored in the registry property. The complete GetPsVersionWmi.Ps1 script is seen here:

$hklm = 2147483650
$key = "SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine"
$value = "RunTimeVersion"
$wmi = [wmiclass]"root\default:stdRegProv"
($wmi.GetStringValue($hklm,$key,$value)).svalue

We can also use the .NET Framework classes to obtain information from the registry. To do this, we use the Microsoft.Win32.Registry .NET Framework class. We use the GetValue static method, which takes three parameters. The first parameter is the registry root and key name. The second parameter is the registry value you wish to read, and the last parameter is the default value of the registry key value. In the GetPsVersionNet.Ps1 script, we assign the HKEY_LOCAL_MACHINE string value to the $hklm variable. Next we assign the string representing the remainder of the registry path to the $key variable. The registry key property value we wish to retrieve is stored in the $value variable. We then use the [Microsoft.Win32.Registry] class and use the two colons to signify that we wish to use a static method and then use the GetValue method with the $hklm, $key, and $value parameters passed to it. The GetPsversionNet.ps1 script is seen here:

$hklm = "HKEY_LOCAL_MACHINE"
$key = "SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine"
$value = "RunTimeVersion"
[Microsoft.Win32.Registry]::GetValue("$hklm\$key",$value,$null)

Well, WS, as you have seen, to work with the registry there is a Windows PowerShell provider, a COM object, a WMI class, and a .NET Framework class. This plethora of methodologies is one of the big strengths of Windows PowerShell. It is also a significant source of confusion for people just learning Windows PowerShell. What is the best thing to use? If you are just making the transition from VBScript, use whatever is most comfortable to you.

I personally like using regread from the wshshell object. It is easy, fast, and makes sense. When I need to connect to a remote computer, I use WMI. I almost never use the .NET version. At times, however, I like the simplicity of using the Windows PowerShell provider. It makes it very easy to use. Stay tuned. We will be working with the registry all this week, and maybe by the end of the week you will find what works for you. See you tomorrow. Peace.

 

Ed Wilson and Craig Liebendorfer, Scripting Guys

Author

0 comments

Discussion are closed.