Uninstall Java the Easy Way (Redux)

Posted: February 7, 2014 in Automation, Java, powershell
Tags: , ,

Uninstall Java using Powershell and WMI either as a script or module with options to keep a specified version installed and optional list the versions installed.

UPDATE: 1.0 Released, see post here

Download from here if you don’t want to read on: https://poshuninstalljava.codeplex.com

I’ve had a couple of comments from my previous post on uninstalling Java with Powershell. They have been in regards to either enhancing the WMI query or leaving a particular Java version installed. That has spurred me on to rewrite the script in a more complete form and include some optional arguments.

The new script is written as a Powershell module (you’ll see the psm1 extension on the file) so the module will have to be loaded and then called just like a normal cmdlet. There’s lots of info on the web about how to use modules, so I won’t repeat that here, but to quickly load the module use “ipmo .\uninstall-java.psm1” from Powershell.

The cmdlet has two optional arguments:

-KeepVersionJava version number” will uninstall all other versions of Java except the versions that match the string provided. Using “7.0.51” will retain Java version 7 Update 51, for example. Note that this switch does a match on the start of the version string, so passing “7” will keep all updates of the major version 7 whilst uninstalling versions 6 and 5.

-Whatif will flag the cmdlet to not uninstall any software but will output (as an object from WMI) all the software that matches the query that would be uninstalled if the switch was not used. This can also be used to get a list of all versions of Java that are installed as a series of objects that can be piped to other powershell commands or to a text file.

In either mode the cmdlet outputs the results as an array of WMI objects which can be piped into other commands.

I’ve included in the WMI query a set of additional product name matches supplied by a commenter “Carsten” which excludes a number of non Oracle software packages that otherwise would have been accidentally triggered by the cmdlet. There is a line early in the module which sets the base query string which reads something like:

$query=“select * from win32_Product where (Name like ‘Java %’ or Name like ‘Java(TM)%’ or Name like ‘J2SE%’) and (Name <> ‘Java Auto Updater’) and ((Vendor=’Sun Microsystems, Inc.’) or (Vendor=’Oracle’)) and (NOT Name like ‘%CompuGROUP%’) and (NOT Name like ‘%IBM%’) and (NOT Name like ‘%DB%’) and (NOT Name like ‘%Advanced Imaging%’) and (NOT Name like ‘%Media Framework%’) and (NOT Name like ‘%SDK%’) and (NOT Name like ‘%Development Kit%’)“

This is where you can add any other possible strings to exclude from the un-installation process.

A final word of warning. This module was written as a quick way of screening and removing Java from computers in an environment where there hasn’t been a lot of control in terms of software distribution. As you’ll see from the changes to the WMI query, there are a number of software packages that could have been accidentally removed because of the broad query used. I suggest you run the cmdlet with the -Whatif switch and capture the output for review before running properly.

UPDATE: The Win32_Product WMI class will cause the MSI Installer service to scan through all installed applications and generate a number of events (ID 1035) but otherwise does not seem to cause major issues. The Microsoft KB articel is here: http://support.microsoft.com/kb/974524/en-us. There is no way to avoid this and using the Win32_AddRemovePrograms class offers no uninstall() method. For the time being if you want to use this script then I would avoid using it as a login script or s start up script which may slow down login times..

You can download the file from the Codeplex project I’ve started : https://poshuninstalljava.codeplex.com

EDIT: There is now a ps1 version to provide the same functionality but as a script rather than a full module for those who may want to remotely launch or embed in something like SCCM or Group Policy.

  1. Billy says:

    Hello, thank you for the script! It’s useful and also helpful for learning powershell. I do have a question though — I can run the module, and it is successful, but when I try to use the switches I get “a parameter cannot be found that matches parameter name ‘Whatif'” — can you tell me what I’m doing wrong? Thanks!

  2. Billy says:

    Oy, I got it! I was tying to run the argument off the .ps1 files instead of importing the module and then running the cmdlet. Thanks again!

  3. Bill says:

    This is amazing. Quick question from a guy who knows nothing about scripting: Could you tell me how I could make the script look for/keep multiple JRE versions? We have users who need to stay on JRE 6, so my end goal is to uninstall any version of JRE that is below JRE7u51 or JRE6u45. Make sense? Your script works wonder for me when I tell it to keep one version, but obviously it deletes the other. Thanks, man!!

    • If you want to handle multiple versions then I would edit the line that defines the base query (I.E the line starting with “$query=”. Add the following at the end before the last quotation marks but after the last bracket.

      and (NOT Version like ‘7.0.51%’) and (NOT Version like ‘6.0.45%’)

      Don’t use the -KeepVersion switch though.

  4. John Panicci says:

    awesome Script.. one question, how can I run this against remote computers?

    • Totally depends on what you have at your disposal. I’ve made a file update so that there is now a module version (.psm1) and a script version (.ps1). You could us Powershell Remoting if your desktop fleet is modern and fairly static or use SCCM or Group Policy to remotely run the script.

  5. John Panicci says:

    thanks Craig, I figured out how to run it remotely. I have just one issue, apparently using the “-query “select * from win32_Product” causes event ids 1035, a whole bunch that basically say that every product installed was reconfigured or installed. It doesn’t cause an issue that I can see except tons of log entries. Is there a way around this happening?

    • Hi John,
      Yes I’ve seen this and a little research suggests that using Win32_Product triggers msiinstaller and creates those events.
      Apparently there is a different WMI class that is more efficient and doesn’t trigger those events.
      I’ll do some more research and see if I can switch the script to the other WMI class.

      • Update: The Win32Reg_AddRemovePrograms WMI class has no Uninstall() method so it isn’t a direct replacement for Win32_Product in my script. For the time being any use of this script will create a number of 1035 envents in the log.

  6. Chuck Fleury says:

    Java 8 updated the Vendor Name to Oracle Corporation. You can modify line 43 to $query=“select * from win32_Product where (Name like ‘Java %’ or Name like ‘Java(TM)%’ or Name like ‘J2SE%’) and (Name ‘Java Auto Updater’) and ((Vendor=’Sun Microsystems, Inc.’) or (Vendor Like ‘Oracle %’)) and (NOT Name like ‘%CompuGROUP%’) and (NOT Name like ‘%IBM%’) and (NOT Name like ‘%DB%’) and (NOT Name like ‘%Advanced Imaging%’) and (NOT Name like ‘%Media Framework%’) and (NOT Name like ‘%SDK%’) and (NOT Name like ‘%Development Kit%’)“
    This change allows the removal of Java 1.8 installs.

  7. Chuck Fleury says:

    I found that once I changed it the removal for 1.7 stopped working.
    So I updated it again,
    It’s line 40 not 43.
    $query=“select * from win32_Product where (Name like ‘Java %’ or Name like ‘Java(TM)%’ or Name like ‘J2SE%’) and (Name ‘Java Auto Updater’) and ((Vendor=’Sun Microsystems, Inc.’) or (Vendor Like ‘Oracle’)) and (NOT Name like ‘%CompuGROUP%’) and (NOT Name like ‘%IBM%’) and (NOT Name like ‘%DB%’) and (NOT Name like ‘%Advanced Imaging%’) and (NOT Name like ‘%Media Framework%’) and (NOT Name like ‘%SDK%’) and (NOT Name like ‘%Development Kit%’)“

  8. Anyway to remove the Development Kits ?

    • Quickest way would be to edit the query. Find the line starting with $query= (Line 44 in theory) and change the section (NOT Name like ‘%SDK%’) and (NOT Name like ‘%Development Kit%’) by removing the NOT3

      Ideally I’d suggest using the -Whatif switch to test this first.

  9. Special Ed says:

    I see your script looks for Java processes and kills them. Can you help me modify it so it waits for the process to close before it uninstalls? So, if the script is running on a machine a user has Java open, it will uninstall AFTER the user quits the app calling java.

    • I’ll have a look at it and see what I can put together. It has been something I’ve wanted to do as a less brutal upgrade. With SCCM there is however a maximum run time so in a SCCM advertisement it would report a failure when it hit that time and would kill the script.

      UPDATE: I’ve made some changes to the PS1 script version of the code which now includes three new options, two of which work together.
      -Wait will make the script wait for any processes with a name starting with “java” to terminate before continuing. If new java processes start after the script starts waiting then the script will loop and pick up these new processes and begin the wait again until no processes are running.
      -Timeout works with -Wait to specify a “deadline” by specifying the number of seconds to wait before giving up and just terminating the processes. Same approach applies in terms of new processes that are started after the wait begins.
      -Restart will restart the computer if any of the uninstall method calls return 3010 indicating a restart is required.

      I’ve tested the various scenarios with Windows 8.1. I’d appreciate any feedback on how the script goes (or doesn’t go). I’ll be doing some further testing as time allows and updating the PSM1 module version once that’s done.

  10. Daniel says:

    After the update, I’m getting some syntax errors. This is my first time with PS, so thought I would let you know (Windows 7 x64)
    ————– [start error]
    At E:\Packaging\Java\SmartUninstall\Uninstall-Java.ps1:69 char:129
    + … %’) and (Name ‘Java Auto Updater’) and ((Vendor=’Sun Microsystems, Inc.’) or …
    + ~
    Missing file specification after redirection operator.
    At E:\Packaging\Java\SmartUninstall\Uninstall-Java.ps1:69 char:128
    + … E%’) and (Name ‘Java Auto Updater’) and ((Vendor=’Sun Microsystems, Inc.’) or …
    + ~
    The ‘<' operator is reserved for future use.
    At E:\Packaging\Java\SmartUninstall\Uninstall-Java.ps1:69 char:191
    + … ystems, Inc.') or (Vendor='Oracle')) and (NOT Name like '%CompuGROUP%') and (NOT …
    + ~~
    Unexpected token 'or' in expression or statement.
    At E:\Packaging\Java\SmartUninstall\Uninstall-Java.ps1:69 char:190
    + … systems, Inc.') or (Vendor='Oracle')) and (NOT Name like '%CompuGROUP%') and (NO …
    + ~
    Missing closing ')' in expression.
    At E:\Packaging\Java\SmartUninstall\Uninstall-Java.ps1:65 char:5
    + {
    + ~
    Missing closing '}' in statement block.
    At E:\Packaging\Java\SmartUninstall\Uninstall-Java.ps1:69 char:211
    + … endor='Oracle')) and (NOT Name like '%CompuGROUP%') and (NOT Name like '%IBM%') …
    + ~
    Unexpected token ')' in expression or statement.
    + CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : MissingFileSpecification
    ————- [end error]

    • Daniel says:

      You can’t really tell from the error as it posted, but it has an issue with the WMIC query’s syntax like the “” and the “) or (”


      • Daniel says:

        That didn’t post correctly. Sorry to flood. the GreaterThan LessThan symbols, representing NOT did not work.

      • OK The problem is with the push from my local repository up to codeplex using GIT. Certain symbols are being translated. Showing my newbieness with GIT. I’ll sort it out and push again.

        UPDATE: FIXED, it was an issue with my local file encoding with a quotation mark in the WMI query. All fixed and the latest committed version should work.

  11. jwb says:

    This is great! I am a ps person, not vbs, so this works well for me. How about including something to kill IE, etc…. otherwise nag screens pop up. Such as
    get-process iexplore | stop-process -Force -ErrorAction SilentlyContinue
    get-process chrome | stop-process -Force -ErrorAction SilentlyContinue

    • I’ll consider it, but it starts making the script more complicated. I’d be inclined to suggest wrapping the script or module into a parent Powershell script that will kill other processes if that’s required for your particular environment.

  12. Bandar says:

    Saludos desde Argentina. Actualmente estoy aprendiendo PoSh y me agradó mucho ver aplicadas algunas de las Buenas Practicas que sugieren utilizar. Script muy útil. Muchas gracias por compartir tu experiencia.

  13. Eran says:

    This works great! thank you so much.
    As mentioned, for versions>8, update the vendor in query construction.

    If interested in logging, you can add these lines after the uninstall runs:
    $Comp = Get-Content env:computername
    $Date = ( Get-Date ).ToString(‘dd-MMM-yyyy-HH:mm’)
    Add-Content “\\server\share\Log.txt” “`n$Comp – $Date – $($java.name) Uninstalled”

    to get a log with “hostname – timestamp – JREversion Uninstalled”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s