3

I am trying to get my script finished for checking powershell versions on remote machines, and I am now down to one last part, I am getting a version number of the file back from powershell but I am looking for a way to turn 6.2.1200.XXX to Version 3, my script thus far is

Foreach ($Computer in $Computers)
{
    Try
    {
        Write-Host "Checking Computer $Computer"
        $path = "\\$Computer\C$\windows\System32\WindowsPowerShell\v1.0\powershell.exe"
        if (test-path $path)
        {
            Write-host "Powershell is installed::"
            [bool](ls $path).VersionInfo
            Write-host " "
            Write-host "Powershell Remoting Enabled::"
            [bool](Test-WSMan -ComputerName $Computer -ErrorAction SilentlyContinue)
        }
        else
        {
            Write-Host "Powershell isn't installed" -ForegroundColor 'Red'
        }
        Write-Host "Finished Checking Computer $Computer"
    }
Luke
  • 647
  • 1
  • 8
  • 22
  • Please don't try to reverse lookup based on Windows version. This can break in so many dumb ways, such as the user installing PS5 on Win7, a SP bringing new features to old OS, or simply a new OS coming out with a number scheme you haven't seen. Just ask PowerShell what version it's running. `Powershell.exe -C "$PSVersionTable.PSVersion"` – Ryan Bemrose May 28 '15 at 20:53
  • @RyanBemrose your way would work if I could remote powershell to every machine which I can't and it is not checking the version of windows but the version of the powershell file, which is set by the vendor(Microsoft) – Luke May 28 '15 at 21:09

2 Answers2

4

The file versions which include the revision, might change as updates get installed, but the first 3 numbers should be useful. You can cast as a [version] or you can just use a simple split or replace to get rid of the build.

You could then make a hashtable with version numbers as keys and PS versions as values.

$fileVer = [version](Get-Item $path).VersionInfo
$myVer = "{0}.{1}.{2}" -f $fileVer.Major,$fileVer.Minor,$fileVer.Build

$verTable = @{
    '6.3.1200' = 3
    '6.3.9600' = 4
}

$psVer = $verTable[$myVer]

Otherwise, if you've determined that PowerShell remoting is in fact enabled, another way would be to just ask it:

$prEnabled = [bool](Test-WSMan -ComputerName $Computer -ErrorAction SilentlyContinue)
if ($prEnabled) {
    $psVer = Invoke-Command -ComputerName $computer -ScriptBlock { $PSVersionTable.PSVersion.Major }
}

Alternatives for setting $myVer:

String substitution:

$fileVer = [version](Get-Item $path).VersionInfo
$myVer = "$($fileVer.Major).$($fileVer.Minor).$($fileVer.Build)"

Replace (regular expression):

$fileVer = (Get-Item $path).VersionInfo
$myVer = $fileVer -replace '\.\d+$',''
# replaces the last dot and any digits with nothing

Split with range:

$fileVer = (Get-Item $path).VersionInfo
$myVer = ($fileVer -split '\.')[0..2]
# splits on a literal dot, then uses a range to get the first 3 elements of the array

Using switch -wildcard (credit to Ansgar Wiechers):

$fileVer = (Get-Item $path).VersionInfo.ProductVersion
$myVer = switch -Wildcard ($fileVer) {
    '6.3.1200.*' { 3 }
    '6.3.9600.*' { 4 }
}
briantist
  • 45,546
  • 6
  • 82
  • 127
  • 2
    Another option would be to use a `switch -wildcard` statement on the `.VersionInfo.ProductVersion` property. – Ansgar Wiechers May 28 '15 at 19:23
  • @briantist I added in the hash table and got it coded in but now my script stops at that point and goes no further. – Luke May 28 '15 at 19:37
  • @AnsgarWiechers edited it into the answer. I *always* forget about `switch -Wildcard`, thanks! – briantist May 28 '15 at 19:45
  • @Luke do you mean it errors out? Edit the new code into the question, and if there's an error, show that too. – briantist May 28 '15 at 19:45
  • it was the `[version]` part of the statement and it was a logic error, but the switch works great. – Luke May 28 '15 at 19:53
  • @briantist I added the final code as an answer, but when I took out `[version]` it finished just never told me the version. but while it was in there it just stopped at that spot. – Luke May 28 '15 at 19:57
0

The code I ended with is

[CmdletBinding()]
Param (
    [Parameter(Mandatory = $true)]
    $ComputerName
)
if (Test-Path $ComputerName)
{
    $Computers = Get-Content $ComputerName
}
Else
{
    $Computers = $ComputerName
}

Foreach ($Computer in $Computers)
{
    Try
    {
        Write-Host "Checking Computer $Computer"
        $path = "\\$Computer\C$\windows\System32\WindowsPowerShell\v1.0\powershell.exe"
        $fileVer = (Get-Item $path).VersionInfo.ProductVersion
        $myVer = switch -Wildcard ($fileVer)
        {
            '6.0.6002.*' { 1 }
            '6.1.7600.*' { 2 }
            '6.2.9200.*' { 3 }
            '6.3.9600.*' { 4 }
        }

        if (test-path $path)
        {
            Write-host "Powershell is installed::"
            [bool](ls $path).VersionInfo
            Write-host " "
            Write-host "Powershell Version installed::"
            Write-host " $myVer "
            Write-host " "
            Write-host "Powershell Remoting Enabled::"
            [bool](Test-WSMan -ComputerName $Computer -ErrorAction SilentlyContinue)
        }
        else
        {
            Write-Host "Powershell isn't installed" -ForegroundColor 'Red'
        }
        Write-Host "Finished Checking Computer $Computer"
    }

    catch { }
}
Luke
  • 647
  • 1
  • 8
  • 22
  • The `$myVer` variable contains the version. If you want to display it you would use something like `Write-Host $myVer`. – briantist May 28 '15 at 20:14