Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

How can I check if PowerShell v2.0 is installed on a list of servers? The list of servers is a combination of Windows Server 2003 and Windows Server 2008. A vbscript or PS script would be wonderful.

I know PowerShell is installed, by default, in Windows Server 2008, though I just like to make sure somebody was not messing with the servers.

share|improve this question
up vote 2 down vote accepted

After digging around and finding several places that lead to nothing usable in my environment, I was able to find this. This will work on systems that don't have Powershell, so it could be used for other registry scans.

$hostA = “RemoteComputer”
$cred = Get-Credential "domain\username"
$RegPath = "SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine"
$ValueName = "PowerShellVersion"
$tmp = $(gwmi -computername $hostA -class win32_service -Credential $cred | Where-Object { $_.Name -eq “RemoteRegistry” })
if ( $($tmp.State) -eq "Stopped") {$tmp.StartService()}
$reg = Get-WmiObject -credential $Cred -List -Namespace root\default -computername $hosta | Where-Object {$_.Name -eq "StdRegProv"}
$ref = ($reg.GetStringValue(2147483650,$RegPath,$ValueName)).sValue
if ($ref -eq $null ) {Write-Host $hostA "doesn't have Powershell"} else {Write-Host $hostA "has Powershell version" $ref}

Edit: After looking around, it turns out this won't work if the Remote Registry service isn't running. I added code to check for remote registry and start if stopped. The $cred = Get-Credential "domain\username" can be removed along with -Credential $cred depending on your domain setup.

Edit2: Ok, I have found permission issues with using .OpenSubKey(). I am switching it to .GetValueKind(), since all we need to do is verify the key exist. Hopefully this works for you. I don't have the permissions where I work to fully test this for you.

Edit3: I was having a lot of problems with permission in my environment since I cross untrusted domains. I have rewrote the above code to work in my environment. It works remotely, and doesn't require Powershell to be installed. Let me know if you get any other errors.

share|improve this answer
I tested on my PC first. I replaced "RemoteComputer" with "FQDN of my server", and it tells me my PC does not have PowerShell. I am not sure what the value of $ref is and how it works here. – whizkid Jul 12 '12 at 16:04
Are you getting any other errors? I'm in a place I can actually test it, and I'm getting an error getting $regKey to set properly. I'll look into it and see what I can find. – Nick Jul 12 '12 at 17:19
Error says: Exception calling "GetValueKind" with "1" argument(s): "The specified registry key does not exist." At D:\Whiz\MyScripts\findPS1.ps1:7 char:28 + $ref = $regKey.GetValueKind <<<< ("\SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine\PowerShellVersion") + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : DotNetMethodException ... though this script looks OK, looks like something about the way it calls the registry. I am still trying to figure this out. – whizkid Jul 13 '12 at 14:47
I cannot test anything right now, but when I get back to work Monday, I'll see if I can figure out what is going wrong. – Nick Jul 15 '12 at 15:55
I fixed the script above. It is working in my environment. Hopefully this will solve your problem. – Nick Jul 16 '12 at 17:26

You'll need the Microsoft ActiveDirectory Powershell Module, it's included with RSAT. This will issue an error message for machines which are inaccessible for any reason -- offline, No Powershell installed, Powershell v1, etc.

Import-Module ActiveDirectory

# Get all "Windows Servers" from AD
$servers = Get-ADComputer -Filter { OperatingSystem -Like "Windows Server*" }

foreach ($s in $servers) {
    "$($s.Name) $(Invoke-Command -Computer $s.Name -ScriptBlock { $PSVersionTable.PSVersion.Major })"

Per Tony Roth's comment, if you cannot use the ActiveDirectory Module, or ADWS/ADWS Gateway, the following should do the same as above, just using System.DirectoryServices instead.

$domainSearch = New-Object System.DirectoryServices.DirectorySearcher
$domainSearch.Filter = "(&(objectclass=computer)(operatingSystem=Windows Server*))"
$domainResult = $domainSearch.FindAll()
foreach ( $s in $domainResult ) {
  "$($ $(Invoke-Command -Computer $($ -ScriptBlock { $PSVersionTable.PSVersion.Major })"

You're going to want to use $PSVersionTable.PSVersion instead of $host.Version as the latter will return 1 when executing remotely.

share|improve this answer
Another minor requirement is that you'll need the ad web service for this to work. – tony roth Jul 11 '12 at 17:29
@tonyroth Yes, if your domain is not 2008R2, or not running ADWS Gateway, the ActiveDirectory Module will not work. I've added an example that will produce the same results without the module requirement. – jscott Jul 11 '12 at 18:52
Im trying the second script, Invoke-command does not seem to be working, and gives the error: "Connecting to remote server failed with the following error message : The WinRM client cannot complete the operation within the time specified." Do I have to enable WinRM service on the machines ? – whizkid Jul 12 '12 at 15:14
Yes, the quickest way to configure this is [via Group Policy(…). – jscott Jul 12 '12 at 15:24

I'd check this key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine\powershellversion.

share|improve this answer
This is correct. However, with all due respect, I cannot mark this as the answer for the only reason that my query was to check multiple/list of machines. – whizkid Jul 13 '12 at 15:29

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.