How to install JDK from PowerShell silently

A couple of days ago, I have fought long and hard battle against JDK (Java Developer Kit) installation packages. The goal was to deploy the JDK offline to a custom path on a Windows (XP + 7) system using a PowerShell script. The problem was that the jdk.exe installer (the only one available from Sun) has trouble parsing INSTALLDIR value if it contains whitespace (e.g. “C:\Program Files”). Also, PowerShell has trouble interpreting parameters containing with escaped quotes in the middle, like /v"something".

I have slowly pieces together a solution from following sources:

The final PowerShell script looks like this:

$installDir = 'C:\Program Files\JDK\' # Just an example, of course
$arguments = @(
	'/s',
	"/v/qn`" INSTALLDIR=\`"$installDir\`" REBOOT=Supress IEXPLORER=0 MOZILLA=0 /L \`"install.log\`"`""
)

$proc = Start-Process "jdk.exe" -ArgumentList $arguments -Wait -PassThru
if($proc.ExitCode -ne 0) {
	Throw "ERROR"
}

Note the double escape characters in the second argument, which basically contains all the non-switch parameters for the installer. The backslash in “\`"” escapes the double quote for JDK installer program, while the grave accent escapes it for PowerShell. Also note the space before INSTALLDIR=...: for some reason, if it is omitted, the installer will fail.

I have tested that script on both WinXP (32bit JDK) and Win7 (64bit JDK) machines and it works like a charm. It also works for JRE installers, which have similar problems with passing arguments. Oh, and a bit of advice if you install 64bit JDK and 32 bit JRE on the same system: do it in the JRE->JDK order, not the other way around.

UPDATE 21.03.12: Richard Neff suggested adding the info on setting the machine-level environment variable JAVA_HOME in the same script. It’s actually quite simple:

[environment]::SetEnvironmentVariable('JAVA_HOME', $installDir, 'machine')

Enjoy.

This entry was posted in java, msi, powershell. Bookmark the permalink.

20 Responses to How to install JDK from PowerShell silently

  1. Richard Neff says:

    Very useful! This is just the sort of thing I was looking for!

    I’d love to see a part 2 with setting environment variables, such as JAVA_HOME to go with the install.

  2. Joe says:

    Does this still work with current versions of the JRE? I am having problems using this to install jre1.6.0_32.

    • Koveras says:

      Yes, that should work with jre1.6.0_32 unless they changed something. I think I tested it with 1.6.0_29 JDK and JRE…

      What kind of problems are you having? Which Windows version do you use?

  3. Robert R. says:

    Feel free to convert this to Powershell … Useful for installing JRE on both x86 and x64 Platforms.

    Just place the .MSI and the data file in the same directory. I use “Install.cmd” as a common command inside Microsoft Desktop Deployment Toolkit when I deploy latest versions of Java JRE.

    ———————————–Install.cmd———————————
    @Echo Off

    Echo ……………………………………….
    Echo Installing Sun Java Runtime Environment 1.7
    Echo ……………………………………….

    :: Java 7 Install
    msiexec /i jre1.7.0_05.msi /qn IEXPLORER=1 REBOOT=Suppress

    If /i “%PROCESSOR_ARCHITECTURE%”==”AMD64” Goto x64
    If /i “%ProgramFiles%”==”C:\Program Files (x86)” Goto x64

    GOTO END

    :x64
    jre-7u5-windows-x64.exe /s IEXPLORER=1 REBOOT=Suppress

    :END

    :: Disables the Java Update Ability
    REG ADD “HKLM\SOFTWARE\JavaSoft\Java Update\Policy” /v EnableJavaUpdate /t REG_DWORD /d 0 /f
    REG ADD “HKLM\SOFTWARE\JavaSoft\Java Update\Policy” /v EnableAutoUpdateCheck /t REG_DWORD /d 0 /f
    REG ADD “HKLM\SOFTWARE\JavaSoft\Java Update\Policy” /v NotifyDownload /t REG_DWORD /d 0 /f
    REG ADD “HKLM\SOFTWARE\JavaSoft\Java Update\Policy” /v NotifyInstall /t REG_DWORD /d 0 /f
    REG DELETE HKLM\Software\Microsoft\Windows\CurrentVersion\Run /v SunJavaUpdateSched /f

    Echo Installation Complete!!!
    ———————————–Install.cmd———————————

    • Koveras says:

      Hey, sorry for late reply, didn’t see your comment. 🙁

      Your code is mostly identical to mine, plus you edit the registry to disable the Java Update daemon. However, I am pretty sure you can prevent it from getting installed with an installer parameter. I cannot tell you what it is off the bat, but I can look it up next week if you are still interested.

  4. Domyno says:

    How would you fit this JRE parameter into the arguments?
    /INSTALLDIRPUBJRE=

    The forward slash is required for this property and causing me some syntax grief

    • Koveras says:

      Since I don’t know what you already tried, I’d start off simply with the following in line 4:

      "/v/qn`" INSTALLDIR=\`"$installDir\`" REBOOT=Supress IEXPLORER=0 MOZILLA=0 /INSTALLDIRPUBJRE= /L \`"install.log\`"`""

      • Domyno says:

        My apologies, allow me to clarify. I’m trying install the JDK and the JRE into two paths. Tossing in that extra /INSTALLDIRPUBJRE= seems to just makes things go boom. I’m pretty sure it’s just a matter of escaping a quote or two or the that forward slash or adding a quote but I’m just not seeing it……yes


        $JDKInstalldir = 'E:\Program Files\Java\JDK'
        $JREInstalldir = 'E:\Program Files\Java\Jre7'
        $JDKLogdir = "F:\LOGS\JAVA"
        $JDKArguments = @('/s',"/v`" INSTALLDIR=\`"$JDKInstalldir\`" /INSTALLDIRPUBJRE=\`"$JREInstalldir\`" /L*V \`"$JDKLogdir\JavaJDK.install.log`"`

        • Domyno says:


          $JDKFile = "2.JDK-7u25-windows-x64.exe"
          $JDKInstalldir = 'E:\Program Files\Java\JDK'
          $JREInstalldir = 'E:\Program Files\Java\Jre7'
          $JDKLogdir = "F:\LOGS\JAVA"
          $JDKArguments = @('/s',"/v`" INSTALLDIR=\`"$JDKInstalldir\`" /INSTALLDIRPUBJRE=\`"$JREInstalldir\`" /L*V \`"$JDKLogdir\JavaJDK.install.log`"`"")

          • Koveras says:

            Hmm, I don’t see any syntax errors, either. So I am afraid you will have to experiment until you get it to work… Try removing the forward slash, for instance, or escaping it with a backward slash first; also, try changing the order of the parameters. Do those parameters work when you install JDK/JRE from CMD console?

            If nothing helps, try downloading a separate JRE installer and installing it separately afterwards. I’ve googled the /INSTALLDIRPUBJRE parameter and it seems that a lot of people have trouble with it, so it may not be your syntax but the installer itself to blame.

  5. Domyno says:

    You may be right about the installer itself being flaky.

    When the forward slash is removed, the installer ignores the parameter and installs the JRE in the default C:\prog… folder. If I escape it, it’s either ignored or throws an error.
    I haven’t tried via CMD but I have done it like this via powershell:

    Start-Process jdk.exe -ArgumentList '/s INSTALLDIR=E:\ProgramFiles\JDK /INSTALLDIRPUBJRE=E:\ProgramFiles\Jre /L*V F:\Logs\Java\install.log'

    This works, but once I use a path with a space (whole point of your thread/script here) and start using variables, quotes and escapes that’s where things fall apart.

    Like you mentioned, I may have to just install them separately via two msi’s.
    Thanks

    • Koveras says:

      Well, the way I would do it is simply start off with the working code and do a step-by-step debugging until I find the exact spot that’s causing the error, then see whether I can find a workaround. But if you need a solution fast, using two installers may be your safest bet.

      Also, your post gave me another idea. Try this and tell me if it works:

      $JDKArguments = @('/s',"/v`" INSTALLDIR=\`"$JDKInstalldir\`" /L*V \`"$JDKLogdir\JavaJDK.install.log`"`"", "/INSTALLDIRPUBJRE=\`"$JREInstalldir\`"")

  6. Domyno says:

    It was a no go, but good try though. I played with a few variations of the suggested changes but nothing but exit code 1639 all over the place. (invalid parameter)

    I’ll play with it a big longer but i’ll probably end up going with the dual msi approach unfortunately.

  7. JAEddy says:

    Has anyone ever come up with a satisfactory solution to the /INSTALLDIRPUBJRE issue? Banging my head against it now for several days without success. I tried Excluding the public jre so that I could install it separately, but I run into the same sort of problem: passing the additional parameters to the installer makes it choke- msiexec calls out invalid parameters. quite frustrating.

    My code (actually, your code) as it currently exists:

    Get-Content Data.txt | Foreach-Object{
    $var = $_.Split(‘=’)
    New-Variable -Name $var[0] -Value $var[1]
    }

    $arguments = @(
    ‘/s’
    ” INSTALLDIR=`”$JDKDir`” `/INSTALLPUBJRE=`”$JREDir`” /L*V C:LogsJavainstall.log”
    )

    $proc = Start-Process $jdkinstaller -ArgumentList $arguments -Wait -PassThru
    if($proc.ExitCode -ne 0) {
    Throw $proc.ExitCode
    }

    The variables contain the executable path and the installation folders (no spaces in any of them, by the way). If I eliminate the /INSTALLDIRPUBJRE as follows, it installs fine, but the public jre lands in Program Filesjava:

    Get-Content Data.txt | Foreach-Object{
    $var = $_.Split(‘=’)
    New-Variable -Name $var[0] -Value $var[1]
    }

    $arguments = @(
    ‘/s’
    ” INSTALLDIR=`”$JDKDir`” /L*V C:LogsJavainstall.log”
    )

    $proc = Start-Process $jdkinstaller -ArgumentList $arguments -Wait -PassThru
    if($proc.ExitCode -ne 0) {
    Throw $proc.ExitCode
    }

    • Koveras says:

      No, sorry, I haven’t really heard of any solution except suppressing the JRE installation with the JDK and installing it separately. 🙁

  8. Srikanth says:

    msiexec is not allowing me to execute the above code at run time
    Any suggestions.

    • Koveras says:

      What exactly is the error message?

      That said, you shouldn’t use msiexec for this install at all, since Java comes with its own executable installer…

Comments are closed.