PowerShell Solution to Java Version

I have to verify many patch statuses each month. A few days ago, I needed to get the current version of Java installed on all of my servers. Obviously I wasn’t going to log into every box, so I needed a remote method. Of course PowerShell could come to my rescue, but which method would be best?

After a little bit of research online, I discovered that there are numerous of ways to find the version of Java installed, but these are not all created equally, I’ve mentioned a few below, along with my final script at the bottom.

WMI Performing a WMI query was by far the worst method to get Java. I can’t actually tell you if it works, because the query did not complete. I even tried running it again the entire time I was writing this post. I didn’t get to the point of trying to filter or refine the result to fit my needs, let alone make it work remotely. Just pass over this code and continue to the useful ones below.

Get-WmiObject -Class Win32_Product | Where { $_.Name -like "Java" }

Registry Key Reading the registry though Get-ItemProperty is quick and easy if you want to pull the local server. It gets much tougher if you want to read remotely though. My remote registry read will work here as well, but the registry key was not showing the version level detail I needed. Java 1.8.0_xx isn’t enough, I need to know each computer has Java 8.0.xxx.xx installed; I need the build number.

Local Only Query

$Key ='HKLM:\Software\JavaSoft\Java Runtime Environment'
(Get-ItemProperty -Path $Key -Name Java7FamilyVersion).Java7FamilyVersion

Remote Query

$Computer = "$Env:ComputerName"
$Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine',$Computer)
$RegKey= $Reg.OpenSubKey("Software\JavaSoft\Java Runtime Environment")
$RegKey.GetValue("Java7FamilyVersion")

Get-ChildItem The idea of this method seemed strange to me, but it actually worked the best, so it’s what I used for my final solution. In its purest form, you just get the details of the java executable and then display the version info.

(Get-ChildItem "C:\Program Files\Java\jre*\bin\java.exe").VersionInfo.ProductVersion

Below is my full version of the script, designed with remote querying in mind and error handling.

Final Solution

# Update $Computers to reflect your server list
$Computers = (Get-Content C:\Users\$Env:UserName\Desktop\AllServers.txt)
ForEach ( $Computer in $Computers )
{
$PingStatus = Gwmi Win32_PingStatus -Filter "Address = '$Computer'" | Select-Object StatusCode
IF ($PingStatus.StatusCode -eq 0)
{
IF (Test-Path ("\\$Computer\C$\Program Files\Java\jre*\bin\java.exe"))
{
$Java = gci "\\$Computer\C$\Program Files\Java\jre*\bin\java.exe"
$Java | Select @{n='Computer';e={$Computer}},@{n='JavaVersion';e={$java.VersionInfo.ProductVersion}}

}
ELSEIF (Test-Path ("\\$Computer\C$\Program Files (x86)\Java\jre*\bin\java.exe"))
{
$Java = gci "\\$Computer\C$\Program Files (x86)\Java\jre*\bin\java.exe"
$Java | Select @{n='Computer';e={$Computer}},@{n='JavaVersion';e={$java.VersionInfo.ProductVersion}}

}
ELSE
{
$Computer | Select @{n='Computer';e={$Computer}},@{n='JavaVersion';e={'-'}}
}
}#EndIf
ELSE
{
$Computer | Select @{n='Computer';e={$Computer}},@{n='JavaVersion';e={'ConnectFailed'}}
}
}#EndForEach

Most of the final script is just error handling. My first If statement tests if the server is pinging, then If statement nested within that tests for Java on a 64 or 32 bit system. This way, I know what version of Java is installed, if no Java is installed, or if the connection failed entirely.

Advertisements

SQL Version Mismatch

Quote

I came across a peculiar issue a few days ago while patching SQL Server. A security scan alleged that one of the SQL Servers was under patched, meaning it was missing the latest required hotfix. A colleague jumped on the problem and began researching.

Probably the first thing we do to verify that SQL Server is running the correct version is to do a simple

SELECT @@VERSION

This of course returns the current version that your server is patched to.

SQL 2014 Test Lab Query
InitialVersion
I apologize for the sparse lab screenshots, but I was unable to recreate this issue quickly in a lab.

Everything looked great from the query, it matched the version that all of the other boxes were running, and the server was reporting that it had the mandated hotfix. Obviously this was a case of a scan that has just failed to connect to the box. A network glitch causing a false positive? Not the first time, won’t be the last. However, we have to prove beyond a shadow of a doubt that everything is in order, so the next step was jumping on the box itself and investigating.

The hotfix was confirmed to be in the installed updates. For good measure, my colleague verified that the SQL Installation Manager agreed. Booting up the hotfix installation file revealed that the SQL Instance was not reporting that the hotfix was installed, nor would it let us install it, but the Shared Services were fine, showing the correct recent patch. Whoa, what’s going on here?

By this time, things were starting to look dicey, and my colleague’s shift was ending. There was talk of doing horrifying things the next day if nothing was resolved. Things like repairing the SQL Installation or even a full Reinstallation. I offered to take a look as a fresh pair of eyes, not expecting to find anything, but just to get up to date on what was going on and as a last-ditch effort before wiping the world clean.

I started poking around and realized that the SQL Shared Services were registering as a different version than the SQL Server Instance. Well, that sounded bad. I thought that if we at least matched those versions up, we could get somewhere after that. It was agreed that this couldn’t hurt anything, so I uninstalled the more recent patch on the Shared Services to match with what the SQL Instance should have been.

Still nothing.

Ok, obviously there is something very wrong now. There had to be something we were missing.

And there was. Something simple and obvious.

In defeat, I finally took the time to just stare at the Installation Manager. I took a few moments to really read the whole screen.

That’s when I saw it. There is a box detailing the installed version of each SQL component on the box, and somehow everyone who had touched it overlooked the message here. The SQL Instance was reporting an incomplete update. Of course it would not let us patch the hotfix because it did not have the Cumulative Update required! It refused to install the Cumulative Update because it was reporting that SQL Server RTM was installed. No hot fixes. No service pack. Nothing. What?? How did no one catch this!

SQL Update for SQL 2014 as reference
WindowsUpdate

Once I saw that, I immediately started a service pack installation, if only to verify that it would be accepted. The Installation Manager was more than happy to oblige now that I wasn’t skipping versions. The necessary cumulative updates and hot fixes went smoothly after that.

In summation, please remember to slow down and really assess the problem at hand. Don’t jump into a problem trying to fix it before you know what is going on and possibly make matters worse. SQL is very good at providing hints, or in this case, blatant answers to your problems. You just need to step back and know where to look. Yes, we all had done SQL installs before, and yes, we all knew about the version information. In the heat of the moment though, we all tried to fire first and ask questions later for something that appeared like a simple problem.

I do find it disconcerting that a SQL Instance would report a patch level of the Shared Instances instead of the instance itself through SELECT @@VERSION. I tried to recreate the scenario in a lab, but SQL responded with the correct version each time. Whatever caused the incomplete installation caused the version information to report back incorrectly through SQL.