In the last few years, the Java developers changed how updates to the Java Runtime Environment (JRE) are installed. Their installer first uninstalls any old version of Java on your computer, and then installs the latest version. This is a good practice, as it keeps outdated versions of JRE from making your system vulnerable to malware and known exploits. But what happens when it fails?
When the uninstallation utility fails to completely remove an old version of Java, you can find yourself stuck. The Java installer won’t allow you to install the new version until the old version is eradicated, but running the uninstaller in Add/Remove Programs doesn’t work. The Java documentation points people to an old Microsoft support page to download the “Office Installation Cleanup Utility”, but the utility is no longer published by Microsoft. This can leave users searching around for hours on sketchy 3rd party sites trying to find the tool. There is literally no technical support for end users who experience Java problems. And it’s no better for enterprise folks either – that support email address bounces messages. I’m pretty ticked at the Java developers’ lack of support and buggy software. But being ticked doesn’t get Java updated.
After a good bit of googling, I eventually found several tools that can help. For those in the enterprise, I have a batch script that you can push as a Group Policy Object (GPO) startup script that will detect if Java is broken or outdated, and upgrade it.
End Users and Single Computers
For end users and single machines, the easiest tool is the Microsoft Office Installer Cleanup Utility, available for download at http://majorgeeks.com/download.php?det=4459. After you install this utility, you can run it and see a list of all the software that is presently installed on your system. Note that you do not want to attempt to uninstall something via this utility first. This utility is a last-ditch effort to remove something from your computer. Once you highlight and remove Java, you should be able to install the latest version. Easy as pie.
For Systems Administrators in the Enterprise
For the enterprise, it gets more tricky. Since you probably don’t want to go around to thousands of computers to click through this program every time Java releases an update, you’ll need to develop some installation scripts. First, you’ll need to obtain the MSI installer for the latest version of Java. Instructions on how to do this are found here: http://www.edugeek.net/forums/windows/64371-how-create-deployable-java-msi-based-r6-u22.html.
Following the guide in the above link, you’ll want to create a MSI transform file (.MST) for deployment. The transform file will do neat things like bypassing the EULA acceptance, enabling the browser plugin, and disabling the auto-update checks (since you’ll be pushing out updates on your own, and your users likely do not have administrator rights – I hope!). To modify MSI’s, as well as generate the transform files, you’ll need Orca, which is free, and located here: http://www.technipages.com/download-orca-msi-editor.html.
Now you should have your MSI and MST files ready to go. They need to be stored somewhere our scripts can access. They’ll run as the computer account if they’re startup scripts, so the computer will need NTFS rights (if you’re going SMB). Alternatively, you could potentially hosts this on your intranet WWW site (though I haven’t tested this).
There are 2 scripts. One is a simple batch script, and the other is a VBS script. The VBS script is called by the batch script, so it, too, will need to be accessible to the computer account. Both scripts require customization for your environment. The VBS script installs Java. The batch script determines if Java needs to be installed.
Without further delay, here’s the VBS script:
‘# Galen Dobbs – 13:20 23/03/2009
‘# If the current version is not installed, it installs it from the specified path.
‘# Based on a script by ‘Daz’ from Appdeploy.com message boards.
‘# http://www.appdeploy.com/messageboards/tm.asp?m=29809Option Explicit
Dim wshShell, fso, strLogFile, ts, strTempDir, strTempISS, strUnString, tsIn
Dim strUninstLine, CLSID, search5, search6, search7, strJRE1, strDisplayName, strDisplayVersion
Dim strPublisher, strUninstallString, strJREUninstallString, strJREDisplayName
Dim search1, search2, search3, search4, strJREUninstallStringNEW, ret, strUninstCMD
Dim tsISS, strSetupexe, qVal, strComputername, strCurrentVersion, strInstallMST
Dim searchCurVer, CurVerFound, strArrayCount, strLogPath, strInstallCMD, strInstallMSI, strInstallLogDim arrayJREDisplayName()
Dim arrayJREUninstallString()‘# Change this to match the version that you don’t want to have it uninstall
strCurrentVersion = “Java(TM) 6 Update 29″‘# Set these to the desired log path and current version installer location
strLogPath = “C:\Java\”
strInstallMSI = “\\fileserver\jre1.6.0_29.msi”
strInstallMST = “\\fileserver\jre1.6.0_29_1.mst”qVal = 0
strArrayCount = 0
ReDim arrayJREDisplayName(strArrayCount)
ReDim arrayJREUninstallString(strArrayCount)Set wshShell = CreateObject(“WScript.Shell”)
Set fso = CreateObject(“Scripting.FileSystemObject”)strComputername = wshShell.ExpandEnvironmentStrings(“%COMPUTERNAME%”)
‘# Set this to the appropriate command line settings to do a silent MSI install
strInstallLog = strLogPath & “Java_Install_” & strComputername & “.log”
strInstallCMD = “msiexec /I “”" & strInstallMSI & “”" /t “”" & strInstallMST & “”" /QN /Lime “”" & strInstallLog & “”"”If Not fso.FolderExists(strLogPath) Then fso.CreateFolder(strLogPath)
strLogFile = strLogPath & “Java_Uninstall_” & strComputername & “.log”
Set ts = fso.OpenTextFile(strLogFile, 8, True)ts.WriteLine String(120, “_”)
ts.WriteLine String(120, “¯”)
ts.WriteLine Now() & ” – Java Runtime(s) uninstallation started…”
ts.WriteLine String(120, “_”) & vbCrlf‘# Generate Registry extracts from ‘Uninstall’ keys.
PreFlight()‘# Kill Java Processes
KillProc()strTempDir = wshShell.ExpandEnvironmentStrings(“%temp%”)
strTempISS = strTempDir & “\iss”
strUnString = ” -s -a /s /f1″
Set tsIn = fso.OpenTextFile(strTempDir & “\uninstall.tmp”, 1)If Not fso.FolderExists(strTempISS) Then fso.CreateFolder(strTempISS)
Do While Not tsIn.AtEndOfStream
strUninstLine = tsIn.ReadLine
CLSID = Mid(strUninstLine, 73, 38)
search5 = Instr(strUninstLine, “JRE 1″)
search6 = Instr(strUninstLine, “]”)
If search5 > 0 AND search6 > 0 Then
strJRE1 = Replace(Mid(strUninstLine, search5, search6),”]”,”")
End IfOn Error Resume Next
strDisplayName = wshShell.RegRead(“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\” & CLSID & “\DisplayName”)
strDisplayVersion = wshShell.RegRead(“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\” & CLSID & “\DisplayVersion”)
strPublisher = wshShell.RegRead(“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\” & CLSID & “\Publisher”)
strUninstallString = wshShell.RegRead(“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\” & CLSID & “\UninstallString”)strJREUninstallString = wshShell.RegRead(“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\” & strJRE1 & “\UninstallString”)
strJREDisplayName = wshShell.RegRead(“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\” & strJRE1 & “\DisplayName”)On Error Goto 0
‘Search for presence of Java and Sun in DisplayName and Publisher
search1 = Instr(1, strDisplayName, “Java”, 1)
search2 = Instr(1, strPublisher, “Sun”, 1)
search3 = Instr(1, strDisplayName, “J2SE”, 1)
search4 = Instr(1, strUninstallString, “setup.exe”, 1)
search7 = InStr(1, strDisplayName, “Development”, 1) + InStr(1, strDisplayName, “Java DB”, 1)‘See if it is the current version
searchCurVer = InStr(1, strDisplayName, strCurrentVersion, 1)‘If it is, Show that the current version is found
If searchCurVer > 0 Then
CurVerFound = TrueElseIf strJREUninstallString <> “” Then
‘# JRE 1 found
strJREUninstallStringNEW = Replace(strJREUninstallString,” -f”,” -s -a /s /f”)
redim Preserve arrayJREDisplayName(strArrayCount)
redim Preserve arrayJREUninstallString(strArrayCount)
arrayJREDisplayName(strArrayCount) = ” – Found Old JRE: ” & strDisplayName & “ – Version: ” & strDisplayVersion & “, Uninstalling…”
arrayJREUninstallString(strArrayCount) = strJREUninstallStringNEW
strArrayCount = strArrayCount + 1ElseIf search7 = 0 And search1 > 0 Or search3 > 0 And search2 > 0 Then
strUninstCMD = “msiexec.exe /x ” & CLSID & ” /norestart /qn”If search4 > 0 Then
‘# Old InstallShield setup found
Set tsISS = fso.OpenTextFile(strTempISS & “\” & CLSID & “.iss”, 2, True)‘Create Response file for any Java Version
tsISS.WriteLine “[InstallShield Silent]”
tsISS.WriteLine “Version=v6.00.000″
tsISS.WriteLine “File=Response File”
tsISS.WriteLine “[File Transfer]”
tsISS.WriteLine “OverwrittenReadOnly=NoToAll”
tsISS.WriteLine “[" & CLSID & "-DlgOrder]”
tsISS.WriteLine “Dlg0=” & CLSID & “-SprintfBox-0″
tsISS.WriteLine “Count=2″
tsISS.WriteLine “Dlg1=” & CLSID & “-File Transfer”
tsISS.WriteLine “[" & CLSID & "-SprintfBox-0]”
tsISS.WriteLine “Result=1″
tsISS.WriteLine “[Application]”
tsISS.WriteLine “Name=Java 2 Runtime Environment, SE v1.4.0_01″
tsISS.WriteLine “Version=1.4.0_01″
tsISS.WriteLine “Company=JavaSoft”
tsISS.WriteLine “Lang=0009″
tsISS.WriteLine “[" & CLSID & "-File Transfer]”
tsISS.WriteLine “SharedFile=YesToAll”
tsISS.ClosestrSetupexe = Left(strUninstallString, search4 + 9)
strUninstCMD = strSetupexe & strUnString & Chr(34) & strTempISS & “\” & CLSID & “.iss” & Chr(34)
End Ifredim Preserve arrayJREDisplayName(strArrayCount)
redim Preserve arrayJREUninstallString(strArrayCount)
arrayJREDisplayName(strArrayCount) = ” – Found Old JRE: ” & strDisplayName & “ – Version: ” & strDisplayVersion & “, Uninstalling…”
arrayJREUninstallString(strArrayCount) = strUninstCMD
strArrayCount = strArrayCount + 1End If
Loop
tsIn.Close
Dim I
If CurVerFound AND strArrayCount > 0 Then
ts.Writeline Now() & ” – Current Version: ” & strCurrentVersion & ” found, continuing with uninstalls…”
For I = LBOUND(arrayJREDisplayName) to UBOUND(arrayJREDisplayName)
ts.WriteLine Now() & arrayJREDisplayName(I)
ts.WriteLine Now() & ” – Uninstall String sent: ” & arrayJREUninstallString(I)
ret = wshShell.Run(arrayJREUninstallString(I) , 0, True)
ts.WriteLine Now() & ” – Return: ” & ret
If ret <> 0 And ret <> 3010 Then qVal = 1
NextElseIf CurVerFound AND strArrayCount = 0 Then
ts.WriteLine Now() & ” – Current version, ” & strCurrentVersion & “, found.”
ts.WriteLine Now() & ” – No Old Java Runtime versions are installed.”
qVal = 99ElseIf Not CurVerFound Then
ts.WriteLine Now() & ” – Current Java version, ” & strCurrentVersion & “, not found, installing it.”
ts.WriteLine Now() & ” – Running Command: ” & strInstallCMD
ret = wshShell.Run(strInstallCMD , 0, True)
If ret <> 0 AND ret<> 3010 Then
ts.WriteLine Now() & ” – Failed to Install Java, see ” & strInstallLog & ” for more details. Exiting Script.”
qVal = 1
ElseIf strArrayCount > 0 Then
ts.WriteLine Now() & ” – Successfully installed ” & strCurrentVersion & “, and logged to ” & strInstallLog & “.”
For I = LBOUND(arrayJREDisplayName) to UBOUND(arrayJREDisplayName)
ts.WriteLine Now() & arrayJREDisplayName(I)
ts.WriteLine Now() & ” – Uninstall String sent: ” & arrayJREUninstallString(I)
ret = wshShell.Run(arrayJREUninstallString(I) , 0, True)
ts.WriteLine Now() & ” – Return: ” & ret
If ret <> 0 And ret <> 3010 Then qVal = 1
Next
ElseIf strArrayCount = 0 Then
ts.WriteLine Now() & ” – Successfully installed ” & strCurrentVersion & “, and logged to ” & strInstallLog & “.”
ts.WriteLine Now() & ” – No Old Java Runtime versions are installed.”
qVal = 99
End If
End Ifts.WriteLine String(120, “_”)
ts.WriteLine String(120, “¯”)
ts.Close
fso.DeleteFolder(strTempISS)
fso.DeleteFile(strTempDir & “\uninstall.tmp”)WScript.Quit(qVal)
Sub PreFlight()
‘# Creates temp files containing extracts from registry ‘Uninstall’ keys.
Dim wshShell, fso, sTemp
Set wshShell = CreateObject(“WScript.Shell”)
Set fso = CreateObject(“Scripting.FileSystemObject”)
sTemp = wshShell.ExpandEnvironmentStrings(“%temp%”)
wshShell.Run “REGEDIT /E %temp%\registry.tmp HKEY_LOCAL_MACHINE\SOFTWARE\microsoft\windows\currentversion\uninstall”, 0, True
wshShell.Run “cmd /c type %temp%\registry.tmp | find /i “”{“” | find /i “”}]”" > %temp%\uninstall.tmp “, 0, True
wshShell.Run “cmd /c type %temp%\registry.tmp | find /i “”JRE 1″” >> %temp%\uninstall.tmp “, 0, True
If Not fso.FileExists(sTemp & “\uninstall.tmp”) Then
ts.WriteLine Now() & ” – No input – %temp%\uninstall.tmp Reg extract not created.”
ts.WriteLine String(120, “_”)
ts.WriteLine String(120, “¯”)
ts.Close
WScript.Quit(1)
End If
End SubSub KillProc()
‘# kills jusched.exe and jqs.exe if they are running. These processes will cause the installer to fail.
Dim wshShell
Set wshShell = CreateObject(“WScript.Shell”)
wshShell.Run “Taskkill /F /IM jusched.exe /T”, 0, True
wshShell.Run “Taskkill /F /IM jqs.exe /T”, 0, True
End Sub
By the way, when you copy/paste VBS text from the internet, make sure your font is converting (straight) quotes into smart (angled) quotes. If you get errors running the VBS, the character conversion could be the cause.
You’ll notice the script is commented, and includes instructions to modify the path to the MSI & MST files, as well as define the current version number. That’s the only modification this script needs.
If you run this script more than once on a good version of Java, it will break, and require a forceful uninstallation. That’s why we’ll call this script with a batch script that checks to see whether we even need to attempt an installation.
@echo off
REM We’ll check for the java executable. If it’s missing, Java is either broken or not installed.
if exist “C:\Program Files (x86)\Java\jre6\bin\java.exe” goto :install
if exist “C:\Program Files\Java\jre6\bin\java.exe” goto :installREM If we get to this point without being forwarded to the install section, we can assume that the Java install is broken. Let’s completely remove it.
reg query hklm\software\classes\installer\products /f “java(tm) 6″ /s | find “HKEY_LOCAL_MACHINE” > C:\windows\logs\deljava.txt
for /f “tokens=* delims= ” %%a in (C:\Windows\logs\deljava.txt) do reg delete %%a /f
del C:\windows\logs\deljava.txt
reg delete “HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment” /f
reg delete “HKEY_LOCAL_MACHINE\SOFTWARE\wow6432node\JavaSoft\Java Runtime Environment” /fREM Java should be completely removed. Now, let’s reinstall it.
REM The Java installer VBS wants C:\Java to exist for logging, so let’s make that.
mkdir C:\Java
REM Now let’s call the installation VBS.
call “\\fileserver\path\to\java_install.vbs”
echo “%time% %date% — Broken Java detected. Uninstalled and re-installed” >> “C:\Windows\logs\java1.txt”
REM And we should be done
goto end:install
REM We know java is installed correctly, let’s see if it needs an update.
if exist “C:\Windows\logs\java1.txt” goto end
REM Change java1.txt with each new version. So next update, we’ll create and check for logfiles called java2.txt
REM If the log file doesn’t exist, we can assume the current version hasn’t been installed. Let’s install it.
REM The Java installer VBS wants C:\Java to exist for logging, so let’s make that first.
mkdir C:\Java
call “\\fileserver\path\to\java_install.vbs”
REM Now Java should be installed with the latest version.
REM Let’s create a log file to check for next time we run this script.
echo “%time% %date% — Java installed” >> “C:\Windows\logs\java1.txt”
:end
As you can see, this is heavily commented. The tricky part is that this script needs to create and look for a log file. If the log file exists, it knows it has already run the script. If the log file doesn’t exist, it knows it should try to install. The tricky part is when you get a new version of Java, you’ll need to modify the VBS with the updated MSI/MSTs, and you’ll need to update the log file that the batch script looks for. So if this version uses C:\Windows\logs\java1.txt, the new version should create and look for C:\Windows\logs\java2.txt.
So there you have it. With this in my shop, we’re able to deploy Java via startup scripts, determine if the installation is broken and reinstall it, and upgrade it. We went from having dozens of machines break at every update and require our intervention, to none. It is still pretty hands on, but until the Java developers manage to create a functional installation utility, this is the best we’ve got.
If you have any tips, troubles, hints, etc., please leave them in the comments below. Happy travels fellow sysadmins!
AIM
Email
Facebook
Flickr
Google
LinkedIn
Skype
Twitter
Facebook comments: