【问题标题】:Check Java is present before installing在安装之前检查 Java 是否存在
【发布时间】:2010-11-20 19:57:30
【问题描述】:

我正在为 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?

【问题讨论】:

    标签: inno-setup registry java


    【解决方案1】:

    我希望有人觉得这很有用,我所做的是重用放置在 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;
    

    感谢大家的帮助

    【讨论】:

    • 您的脚本是否也支持安装 JRE/JDK?许多用户获得了 Java,然后没有安装 JDK。
    【解决方案2】:

    我稍微修改了你的代码,我认为这样会支持更新版本的 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.
    

    【讨论】:

      【解决方案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() 实际上可用于比较字符串中的版本, 如果您想检查确切的版本而不是“至少”,您可以将&gt;= 0 更改为=0

      如果您想取消整个安装,以防用户通过取消或由于错误而无法完成 Java 安装,也可以使用 Exec() 代替 [Run]

      【讨论】:

        【解决方案4】:

        关于您的第三个问题,请参阅商标和许可部分下的 here。执行摘要:您可以将 JRE 与您的应用程序一起分发。我认为一些应用程序这样做是为了确保它们没有版本兼容性问题 - 即将 JRE 安装在应用程序本身的子文件夹中。

        至于在 PATH 中,为什么这很重要?您可以创建一个通过其完整路径引用 java.exe 的快捷方式来运行您的应用程序。用户自己通过命令行启动程序重要吗?

        【讨论】:

        • 我不想将整个 JRE 与我的应用程序捆绑在一起,这给安装程序增加了太多的重量,如果用户已经拥有它,则可能是不必要的。第二个建议看起来不错。看起来我也可以找到从注册表中获取 java 主目录的位置...
        • 你有任何链接到如何做 java.exe 的完整路径吗?
        【解决方案5】:

        对已定义代码的更多增强:

        1. 检查是否存在 JRE/JDK。
        2. 在 32 位或 64 位注册表视图中进行验证。

        代码:

        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.
        

        【讨论】:

        • 据我所知,您只将视图添加到了不同的注册表根目录中。此外,您已经复制了所有错误的代码......
        • 正如您正确提到的,我将 Win64 机器中的检查添加到注册表根 HKLM64。您没有注意到的是,检查现在也包括路径 SOFTWARE\JavaSoft\Java Development Kit
        【解决方案6】:

        已经提出的答案的简单替代方案:

        [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;
        

        【讨论】:

        • 这是否检查特定版本的 Java?如果找到 1.5 怎么办?
        【解决方案7】:

        您可以使用

        ,而不是检查特定版本
        function RegKeyExists(const RootKey: Integer; const SubKeyName: String): Boolean;
        

        获取HKLM\SOFTWARE\JavaSoft\Java Runtime Environment的子键。 (是否可以并行安装不同版本?不知道...)您需要做一些字符串摆弄来检查是否安装了 1.6 或更高版本,但它比检查特定版本号更灵活。

        【讨论】:

          【解决方案8】:

          对于那些可能觉得它有用的人,我编写了一个开源(LPGL 许可)Windows DLL 来检测 Java 安装细节。

          文档:https://github.com/Bill-Stewart/JavaInfo

          下载链接:https://github.com/Bill-Stewart/JavaInfo/releases

          下载包含一个示例 Inno Setup .iss 脚本,该脚本演示了如何使用 DLL 函数。

          JavaInfo.dll 可让您完成以下任务(对安装程序很有用):

          • 检测是否安装了Java
          • 检查安装的Java是32位还是64位
          • 检查安装的 Java 是否至少是最低版本
          • 获取已安装的 Java 主目录
          • 获取已安装的 Java 版本

          DLL 的优点之一是它支持 Java 的多个“品牌”(Sun、AdoptOpenJDK、Zulu、Amazon 等),并且无论安装哪个“品牌”都可以智能地检测 Java。

          【讨论】:

            猜你喜欢
            • 2011-03-25
            • 2021-10-16
            • 2019-05-12
            • 1970-01-01
            • 2012-01-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-10-26
            相关资源
            最近更新 更多