When installing my Java app with Inno Setup, I would like the installer to check if Java 7 or above is present, and install it if needed. But apparently, my current code fails to detect Java 8 on the computer of some of my clients. I couldn't reproduce the bug, though. Do you see something that I could be missing? Maybe this code doesn't work with recent Windows?
Basically, I just check the registry for Java >= 1.7.
[Code]
function InitializeSetup(): Boolean;
var
ErrorCode: Integer;
JavaInstalled : Boolean;
ResultMsg : Boolean;
Versions: TArrayOfString;
I: Integer;
regRoot: Integer;
begin
{ Check which view of registry should be taken: }
regRoot := HKLM
begin
if IsWin64 then
begin
regRoot := HKLM64
end;
end;
if (RegGetSubkeyNames(regRoot, 'SOFTWARE\JavaSoft\Java Runtime Environment', Versions)) or (RegGetSubkeyNames(regRoot, 'SOFTWARE\JavaSoft\Java Development Kit', Versions)) then
begin
for I := 0 to GetArrayLength(Versions)-1 do
if JavaInstalled = true then
begin
//do nothing
end else
begin
if ( Versions[I][2]='.' ) and ( ( StrToInt(Versions[I][1]) > 1 ) or ( ( StrToInt(Versions[I][1]) = 1 ) and ( StrToInt(Versions[I][3]) >= 7 ) ) ) then
begin
JavaInstalled := true;
end else
begin
JavaInstalled := false;
end;
end;
end else
begin
JavaInstalled := false;
end;
if JavaInstalled then
begin
Result := true;
end else
begin
ResultMsg := MsgBox(ExpandConstant('{cm:JavaRequired}'), mbConfirmation, MB_YESNO) = idYes;
if ResultMsg = false then
begin
Result := false;
end else
begin
Result := true;
ShellExec('open', 'http://www.java.com/getjava/', '','',SW_SHOWNORMAL,ewNoWait,ErrorCode);
end;
end;
end;
Edit: This is the final result based on Martin's answer.
[Code]
function CutJavaVersionPart(var V: string): Integer;
var
S: string;
P: Integer;
begin
if Length(V) = 0 then
begin
Result := 0;
end
else
begin
P := Pos('.', V);
if P = 0 then P := Pos('_', V);
if P > 0 then
begin
S := Copy(V, 1, P - 1);
Delete(V, 1, P);
end
else
begin
S := V;
V := '';
end;
Result := StrToIntDef(S, 0);
end;
end;
function MaxJavaVersion(V1, V2: string): string;
var
Part1, Part2: Integer;
Buf1, Buf2: string;
begin
Buf1 := V1;
Buf2 := V2;
Result := '';
while (Result = '') and
((Buf1 <> '') or (Buf2 <> '')) do
begin
Part1 := CutJavaVersionPart(Buf1);
Part2 := CutJavaVersionPart(Buf2);
if Part1 > Part2 then Result := V1
else
if Part2 > Part1 then Result := V2;
end;
end;
function GetJavaVersion(): string;
var
TempFile: string;
ResultCode: Integer;
S: AnsiString;
P: Integer;
begin
TempFile := ExpandConstant('{tmp}\javaversion.txt');
if (not ExecAsOriginalUser(
ExpandConstant('{cmd}'), '/c java -version 2> "' + TempFile + '"', '',
SW_HIDE, ewWaitUntilTerminated, ResultCode)) or
(ResultCode <> 0) then
begin
Log('Failed to execute java -version');
end
else
if not LoadStringFromFile(TempFile, S) then
begin
Log(Format('Error reading file %s', [TempFile]));
end
else
if Copy(S, 1, 14) <> 'java version "' then
begin
Log('Output of the java -version not as expected');
end
else
begin
Delete(S, 1, 14);
P := Pos('"', S);
if P = 0 then
begin
Log('Output of the java -version not as expected');
end
else
begin
SetLength(S, P - 1);
Result := S;
end;
end;
DeleteFile(TempFile);
end;
function HasJava1Dot7OrNewer: Boolean;
begin
Result := (MaxJavaVersion('1.6.9', GetJavaVersion) <> '1.6.9');
end;
function InitializeSetup(): Boolean;
var
ErrorCode: Integer;
begin
Result := HasJava1Dot7OrNewer;
if not Result then
begin
Result := MsgBox(ExpandConstant('{cm:JavaRequired}'), mbConfirmation, MB_YESNO) = idYes;
if Result then
begin
ShellExec(
'open', 'https://www.java.com/getjava/', '', '', SW_SHOWNORMAL, ewNoWait, ErrorCode);
end;
end;
end;
I do not have the
JavaSoft
key inHKLM\Software
. I have it inHKLM\SOFTWARE\WOW6432Node
. What is actually theHKLM\SOFTWARE
in Inno Setup (being 32-bit application).So it looks like you just need to remove the
if IsWin64 then regRoot := HKLM64
block to make it working. Or try both options.For your specific needs, you can check, if Java 1.7 or newer is installed like this:
Or did you consider running
java -version
instead?A bit more efficient implementation of the
InitializeSetup
:Answering my own comment, here's my variation which should work regardless of whether the installed JRE is Oracle's or OpenJDK's, and for Java versions prior to and after Java 9.
The
GetJavaMajorVersion()
function returns the Java version as an integer. For versions wherejava -version
reports "1.x.*" (up to and including Java 8) it will return x, otherwise (Java 9 and later) it will return the actual major number. If for some reason the call tojava -version
fails it will return 0.Lots of room for improvement, but it does the job.