我正在为jar应用创建一个Inno Setup安装程序。 我现在要做的是在继续安装之前检查java是否存在。所以我只需要确保用户能够运行:
java -jar my-app.jar
我现在正在做的是:
[Code]
function InitializeSetup(): Boolean;
var
ErrorCode: Integer;
JavaInstalled : Boolean;
Result1 : Boolean;
begin
JavaInstalled := RegKeyExists(HKLM,'SOFTWARE\JavaSoft\Java Runtime Environment\1.6');
if JavaInstalled then
begin
Result := true;
end else
begin
Result1 := MsgBox('This tool requires Java Runtime Environment version 1.6 or newer to run. Please download and install the JRE and run this setup again. Do you want to download it now?',
mbConfirmation, MB_YESNO) = idYes;
if Result1 = false then
begin
Result:=false;
end else
begin
Result:=false;
ShellExec('open',
'http://javadl.sun.com/webapps/download/AutoDL?BundleId=33787',
'','',SW_SHOWNORMAL,ewNoWait,ErrorCode);
end;
end;
end;
end;
我的问题是:
检查注册表是否足以确保java的主目录将在PATH中? (能够在控制台中运行“java”)
如果安装了更高版本的java,无论如何都会存在注册表中的密钥,或者我是否需要检查每个更高版本?
有没有人有更好的方式来下载java,而不仅仅是显示弹出窗口并将用户带到下载页面?
答案 0 :(得分:14)
我希望有人发现这很有用,我所做的就是重复使用Inno Setups wiki中的一些代码来制作一个< >与版本作为数字进行比较:
{ Both DecodeVersion and CompareVersion functions where taken from the wiki }
procedure DecodeVersion (verstr: String; var verint: array of Integer);
var
i,p: Integer; s: string;
begin
{ initialize array }
verint := [0,0,0,0];
i := 0;
while ((Length(verstr) > 0) and (i < 4)) do
begin
p := pos ('.', verstr);
if p > 0 then
begin
if p = 1 then s:= '0' else s:= Copy (verstr, 1, p - 1);
verint[i] := StrToInt(s);
i := i + 1;
verstr := Copy (verstr, p+1, Length(verstr));
end
else
begin
verint[i] := StrToInt (verstr);
verstr := '';
end;
end;
end;
function CompareVersion (ver1, ver2: String) : Integer;
var
verint1, verint2: array of Integer;
i: integer;
begin
SetArrayLength (verint1, 4);
DecodeVersion (ver1, verint1);
SetArrayLength (verint2, 4);
DecodeVersion (ver2, verint2);
Result := 0; i := 0;
while ((Result = 0) and ( i < 4 )) do
begin
if verint1[i] > verint2[i] then
Result := 1
else
if verint1[i] < verint2[i] then
Result := -1
else
Result := 0;
i := i + 1;
end;
end;
{ Here's my code }
function InitializeSetup(): Boolean;
var
ErrorCode: Integer;
JavaVer : String;
Result1 : Boolean;
begin
RegQueryStringValue(HKLM, 'SOFTWARE\JavaSoft\Java Runtime Environment', 'CurrentVersion', JavaVer);
Result := false;
if Length( JavaVer ) > 0 then
begin
if CompareVersion(JavaVer,'1.6') >= 0 then
begin
Result := true;
end;
end;
if Result = false then
begin
Result1 := MsgBox('This tool requires Java Runtime Environment v1.6 or older to run. Please download and install JRE and run this setup again.' + #13 + #10 + 'Do you want to download it now?',
mbConfirmation, MB_YESNO) = idYes;
if Result1 = true then
begin
ShellExec('open',
'http://www.java.com/en/download/manual.jsp#win',
'','',SW_SHOWNORMAL,ewNoWait,ErrorCode);
end;
end;
end;
感谢大家的帮助
答案 1 :(得分:5)
我稍微改变了你的代码,我认为这样可以支持更新版本的Java; - )
function InitializeSetup(): Boolean;
var
ErrorCode: Integer;
JavaInstalled : Boolean;
Result1 : Boolean;
Versions: TArrayOfString;
I: Integer;
begin
if RegGetSubkeyNames(HKLM, 'SOFTWARE\JavaSoft\Java Runtime Environment', 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]) >= 6 ) ) ) then
begin
JavaInstalled := true;
end else
begin
JavaInstalled := false;
end;
end;
end else
begin
JavaInstalled := false;
end;
//JavaInstalled := RegKeyExists(HKLM,'SOFTWARE\JavaSoft\Java Runtime Environment\1.9');
if JavaInstalled then
begin
Result := true;
end else
begin
Result1 := MsgBox('This tool requires Java Runtime Environment version 1.6 or newer to run. Please download and install the JRE and run this setup again. Do you want to download it now?',
mbConfirmation, MB_YESNO) = idYes;
if Result1 = false then
begin
Result:=false;
end else
begin
Result:=false;
ShellExec('open',
'http://www.java.com/getjava/',
'','',SW_SHOWNORMAL,ewNoWait,ErrorCode);
end;
end;
end;
end.
答案 2 :(得分:3)
现在有另一种方式。您可以添加Stub setup - online installer,它将下载并安装实际设置
现在的文件名是JavaSetup8u121.exe
,这表明它可能是特定于版本的。我没有较旧的版本来测试它是否会下载实际或特定的旧版本
而就目前而言,它似乎只安装了32位JRE。
[Files]
#define JavaInstaller "JavaSetup8u121.exe"
Source: "include\{#JavaInstaller}"; DestDir: "{tmp}";
[Code]
const
REQUIRED_JAVA_VERSION = '1.7';
function isJavaInstalled(): Boolean;
var
JavaVer : String;
tmpFileName,
pathJavaExe: String;
isGoodJavaVersion,
isFoundJavaPath: Boolean;
ResultCode: Integer;
ExecStdout: AnsiString;
begin
{ *** check in registry }
{ sets variables: }
{ JavaVer }
{ isGoodJavaVersion }
if RegQueryStringValue(HKLM, 'SOFTWARE\JavaSoft\Java Runtime Environment',
'CurrentVersion', JavaVer) AND (JavaVer <> '') OR
RegQueryStringValue(HKLM64, 'SOFTWARE\JavaSoft\Java Runtime Environment',
'CurrentVersion', JavaVer) AND (JavaVer <> '') then begin
Log('* Java Entry in Registry present. Version: ' + JavaVer);
isGoodJavaVersion := CompareStr(JavaVer, REQUIRED_JAVA_VERSION) >= 0;
end;
{ add additional checks, for example by searching the PATH, }
{ or by running `java -version` }
Result := isGoodJavaVersion;
end;
[Run]
Filename: "{tmp}\{#JavaInstaller}"; Parameters: "SPONSORS=0"; \
StatusMsg: "Java Runtime Enviroment not installed on your system. Installing..."; \
Check: not isJavaInstalled
在注册表中搜索32位和64位版本,内部函数CompareStr()
实际上可用于比较String中的版本,
如果要查看确切版本而不是“至少”,则可以将>= 0
更改为=0
。
如果您想取消整个安装,以防用户通过取消或由于错误而无法完成Java安装,则可以使用Exec()
代替[Run]
。
答案 3 :(得分:2)
关于第三个问题,请参阅“商标和许可”部分下的here。执行摘要:您可以将JRE与您的应用一起分发。我认为一些应用程序这样做是为了确保它们没有版本兼容性问题 - 即将JRE安装在应用程序本身的子文件夹中。
就PATH而言,为什么这么重要?您可以创建一个快捷方式,通过其完整路径引用java.exe来运行您的应用程序。用户通过命令行自己启动程序是否很重要?
答案 4 :(得分:2)
已定义代码的更多增强功能:
代码:
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('Oracle Java v1.7 or newer not found in the system. Java 1.7 or later is required to run this application (can be installed after this installation too). Do you want to continue?',
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;
end.
答案 5 :(得分:2)
已经提出的答案的简单替代方案:
[Code]
function InitializeSetup(): boolean;
var
ResultCode: integer;
begin
if Exec('java', '-version', '', SW_SHOW, ewWaitUntilTerminated, ResultCode) then begin
Result := true;
end
else begin
if MsgBox('This tool requires Java Runtime Environment version 1.6 or newer to run. Please download and install the JRE and run this setup again. Do you want to download it now?', mbConfirmation, MB_YESNO) = idYes then begin
Result := false;
ShellExec('open', 'https://java.com/download/', '', '', SW_SHOWNORMAL, ewNoWait, ResultCode);
end;
end;
end;
答案 6 :(得分:0)
您可以使用
,而不是检查特定版本function RegKeyExists(const RootKey: Integer; const SubKeyName: String): Boolean;
获取 HKLM \ SOFTWARE \ JavaSoft \ Java运行时环境的子项。 (是否可以并行安装不同版本?不知道......)您需要进行一些字符串摆弄以检查是否安装了1.6或更高版本,但它比检查特定版本号更灵活。
答案 7 :(得分:0)
对于那些可能觉得它有用的人,我编写了一个开源(LPGL 许可)Windows DLL 来检测 Java 安装细节。
文档:https://github.com/Bill-Stewart/JavaInfo
下载链接:https://github.com/Bill-Stewart/JavaInfo/releases
下载包含一个示例 Inno Setup .iss 脚本,演示了如何使用 DLL 函数。
JavaInfo.dll 可让您完成以下操作(从安装程序中很有用):
DLL 的优点之一是它支持多个“品牌”的 Java(Sun、AdoptOpenJDK、Zulu、Amazon 等)并且无论安装哪个“品牌”都能智能检测 Java。