Last active
March 1, 2022 21:12
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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." | |
} |
%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.
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
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.