![](/img/trans.png)
[英]"java -version" command has different results in Inno Setup
[英]Inno Setup, detect Java version
使用 Inno Setup 安裝 Java 應用程序時,我希望安裝程序檢查 Java 7 或更高版本是否存在,並在需要時進行安裝。 但顯然,我當前的代碼無法在我的一些客戶的計算機上檢測到 Java 8。 但是,我無法重現該錯誤。 你看到我可能遺漏的東西了嗎? 也許此代碼不適用於最近的 Windows?
基本上,我只是檢查 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;
編輯:這是基於馬丁回答的最終結果。
[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;
我在HKLM\\Software
沒有JavaSoft
密鑰。 我在HKLM\\SOFTWARE\\WOW6432Node
有它。 Inno Setup(即32位應用程序)中的HKLM\\SOFTWARE
實際上是什么。
所以看起來您只需要刪除if IsWin64 then regRoot := HKLM64
塊即可使其工作。 或者嘗試兩種選擇。
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 GetJavaVersionFromSubKey(RootKey: Integer; SubKeyName: string): string;
var
Versions: TArrayOfString;
I: Integer;
begin
if RegGetSubkeyNames(RootKey, SubKeyName, Versions) then
begin
for I := 0 to GetArrayLength(Versions) - 1 do
begin
Result := MaxJavaVersion(Result, Versions[I]);
end;
end;
end;
function GetJavaVersionFromRootKey(RootKey: Integer): string;
begin
Result :=
MaxJavaVersion(
GetJavaVersionFromSubKey(RootKey, 'SOFTWARE\JavaSoft\Java Runtime Environment'),
GetJavaVersionFromSubKey(RootKey, 'SOFTWARE\JavaSoft\Java Development Kit'));
end;
function GetJavaVersion: string;
begin
Result := GetJavaVersionFromRootKey(HKLM);
if IsWin64 then
begin
Result := MaxJavaVersion(Result, GetJavaVersionFromRootKey(HKLM64));
end;
end;
對於您的特定需求,您可以檢查是否安裝了 Java 1.7 或更高版本,如下所示:
function HasJava1Dot7OrNewer: Boolean;
begin
Result := (MaxJavaVersion('1.6.9', GetJavaVersion) <> '1.6.9');
end;
或者您是否考慮過運行java -version
?
function GetJavaVersion2: 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;
InitializeSetup
更有效實現:
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;
回答我自己的評論,這是我的變體,無論安裝的 JRE 是 Oracle 的還是 OpenJDK 的,以及 Java 9 之前和之后的 Java 版本,它都應該起作用。
GetJavaMajorVersion()
函數以整數形式返回 Java 版本。 對於java -version
報告“1.x.*”(直到並包括 Java 8)的版本,它將返回 x,否則(Java 9 及更高版本)它將返回實際的主編號。 如果由於某種原因調用java -version
失敗,它將返回 0。
function GetJavaMajorVersion(): integer;
var
TempFile: string;
ResultCode: Integer;
S: AnsiString;
P: Integer;
begin
Result := 0;
{ execute java -version and redirect output to a temp file }
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');
exit;
end;
{ read file into variable S }
LoadStringFromFile(TempFile, S)
DeleteFile(TempFile);
Log(Format('java -version output: ' + #13#10 + '%s', [S]));
{ extract version (between quotes) }
P := Pos('"', S);
Delete(S, 1, P);
P := Pos('"', S);
SetLength(S, P - 1);
Log(Format('Extracted version: %s', [S]));
{ extract major }
if Copy(S, 1, 2) = '1.' then
begin
Delete(S, 1, 2)
end;
P := Pos('.', S);
SetLength(S, P - 1);
Log(Format('Major version: %s', [S]));
Result := StrToIntDef(S, 0);
end;
function InitializeSetup(): boolean;
var
ResultCode: Integer;
begin
if GetJavaMajorVersion >= 8 then
begin
Result := true;
exit;
end;
if MsgBox('This tool requires a Java Runtime Environment version 1.8 or newer to run. ' +
'Please download and install the JRE and run this setup again. ' +
'Would you like to open the JRE download page now?', mbCriticalError, MB_YESNO) = idYes then
begin
Result := false;
ShellExec('open', 'https://java.com/download/', '', '', SW_SHOWNORMAL, ewNoWait, ResultCode);
end;
end;
有很大的改進空間,但它可以完成工作。
我想要一些可以在多個 Inno Setup 項目中使用的東西,所以我編寫了一個 DLL 來檢測 Java 詳細信息(主目錄等):
https://github.com/Bill-Stewart/JavaInfo
從這里下載: https : //github.com/Bill-Stewart/JavaInfo/releases
該下載包括一個示例 Inno Setup .iss
腳本,該腳本演示了如何使用 DLL 函數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.