Skip to content

Instantly share code, notes, and snippets.

@tathamoddie
Last active March 1, 2022 21:12
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save tathamoddie/6817880 to your computer and use it in GitHub Desktop.
Attempting to find java.exe, on a Windows machine, in a way that's semi-reliable across Java versions, operating system versions, 32 vs 64-bit and whatever else can be thrown at us.
function Find-JavaExe {
<#
.SYNOPSIS
Locates java.exe on the current system via common conventions.
.DESCRIPTION
Searches $env:JAVAHOME, path variables, and the registry (http://stackoverflow.com/a/5415532/211747)
.EXAMPLE
Find java.exe, or throw an error if it can't be found.
$JavaExePath = Find-JavaExe
.EXAMPLE
Find java.exe, or return null if it can't be found.
$JavaExePathOrNull = Find-JavaExe -ErrorAction SilentlyContinue
#>
[CmdletBinding()]
param ()
$JavaExeSuffix = 'bin\java.exe'
if ($env:JAVAHOME -eq $null) {
Write-Debug "`$env:JAVAHOME doesn't exist, going to look elsewhere"
}
else {
$JavaHomeBasedPath = Join-Path $env:JAVAHOME $JavaExeSuffix
Write-Debug "Testing for $JavaHomeBasedPath, based on `$env:JAVAHOME"
if (Test-Path $JavaHomeBasedPath) {
Write-Debug "Found $JavaExePath"
return $JavaExePath
}
}
$FileSearchPaths = $env:Path.Split(';')
$JavaExePath = $FileSearchPaths |
where {
$PotentialPath = Join-Path $_ $JavaExeSuffix
Write-Debug "Testing for $PotentialPath, based on path variable $_"
if (Test-Path $PotentialPath) { $PotentialPath }
} |
select -First 1
if ($JavaExePath -ne $null) {
Write-Debug "Found $JavaExePath"
return $JavaExePath
}
$RegistrySearchPaths = @('HKLM:\SOFTWARE\JavaSoft\Java Runtime Environment\', 'HKLM:\SOFTWARE\Wow6432Node\JavaSoft\Java Runtime Environment\')
$JavaExePath = $RegistrySearchPaths |
where { Test-Path $_ } |
% {
$CurrentVersion = (Get-ItemProperty $_).CurrentVersion
Write-Debug "Current Java version is $CurrentVersion, based on $($_)"
$VersionKey = Join-Path $_ $CurrentVersion
$JavaHomeBasedPath = Join-Path (Get-ItemProperty $VersionKey).JavaHome $JavaExeSuffix
Write-Debug "Testing for $JavaHomeBasedPath, based on $VersionKey\JavaHome"
if (Test-Path $JavaHomeBasedPath) { $JavaHomeBasedPath }
} |
select -First 1
if ($JavaExePath -ne $null) {
Write-Debug "Found $JavaExePath"
return $JavaExePath
}
Write-Error "We couldn't resolve java.exe. We looked for `$env:JAVAHOME, then checked environment paths and the registry. The full set of search paths were written to the debug output stream."
}
@daveoflynn
Copy link

I seem to recall, but don't have a machine I can test it on to hand, that some JDK/JRE releases put java.exe in %WINSYSDIR%. I don't recall if that directory is explicitly or implicitly in the Windows PATH env variable.

If it isn't, you should also check there directly and early, as it's the version that will be found by most programs.

Copy link

ghost commented Aug 13, 2015

%WINSYSDIR% only contains a pseudo java executable, which reads the registry to check what the default Java version is, then passes on the execution including arguments to the real Java binary.

Copy link

ghost commented Aug 13, 2015

Also, here's my implementation. It avoids the registry and any other config, which are sometimes unreliable and just scans the Program directory for any Java directory that still has a \bin directory (Java updates sometimes remove old versions by deleting the \bin dir)

https://github.com/Orbixx/findjava/blob/master/findJava.ps1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment