【问题标题】:Inno Setup: Verify that .NET 4.0 is installedInno Setup:验证是否安装了 .NET 4.0
【发布时间】:2011-05-05 11:27:44
【问题描述】:

我有一个需要 .NET 4.0 才能运行的组件,我的 Inno Setup 安装程序如何验证它是否已安装,如果没有,提示用户安装它?

【问题讨论】:

    标签: .net inno-setup


    【解决方案1】:

    运行 Inno Setup 可执行文件时会调用 InitializeSetup 函数。为自定义脚本插入此代码应该可以满足您的要求:

    function IsDotNetDetected(version: string; service: cardinal): boolean;
    // Indicates whether the specified version and service pack of the .NET Framework is installed.
    //
    // version -- Specify one of these strings for the required .NET Framework version:
    //    'v1.1'          .NET Framework 1.1
    //    'v2.0'          .NET Framework 2.0
    //    'v3.0'          .NET Framework 3.0
    //    'v3.5'          .NET Framework 3.5
    //    'v4\Client'     .NET Framework 4.0 Client Profile
    //    'v4\Full'       .NET Framework 4.0 Full Installation
    //    'v4.5'          .NET Framework 4.5
    //    'v4.5.1'        .NET Framework 4.5.1
    //    'v4.5.2'        .NET Framework 4.5.2
    //    'v4.6'          .NET Framework 4.6
    //    'v4.6.1'        .NET Framework 4.6.1
    //    'v4.6.2'        .NET Framework 4.6.2
    //    'v4.7'          .NET Framework 4.7
    //    'v4.7.1'        .NET Framework 4.7.1
    //    'v4.7.2'        .NET Framework 4.7.2
    //    'v4.8'          .NET Framework 4.8
    //
    // service -- Specify any non-negative integer for the required service pack level:
    //    0               No service packs required
    //    1, 2, etc.      Service pack 1, 2, etc. required
    var
        key, versionKey: string;
        install, release, serviceCount, versionRelease: cardinal;
        success: boolean;
    begin
        versionKey := version;
        versionRelease := 0;
    
        // .NET 1.1 and 2.0 embed release number in version key
        if version = 'v1.1' then begin
            versionKey := 'v1.1.4322';
        end else if version = 'v2.0' then begin
            versionKey := 'v2.0.50727';
        end
    
        // .NET 4.5 and newer install as update to .NET 4.0 Full
        else if Pos('v4.', version) = 1 then begin
            versionKey := 'v4\Full';
            case version of
              'v4.5':   versionRelease := 378389;
              'v4.5.1': versionRelease := 378675; // 378758 on Windows 8 and older
              'v4.5.2': versionRelease := 379893;
              'v4.6':   versionRelease := 393295; // 393297 on Windows 8.1 and older
              'v4.6.1': versionRelease := 394254; // 394271 before Win10 November Update
              'v4.6.2': versionRelease := 394802; // 394806 before Win10 Anniversary Update
              'v4.7':   versionRelease := 460798; // 460805 before Win10 Creators Update
              'v4.7.1': versionRelease := 461308; // 461310 before Win10 Fall Creators Update
              'v4.7.2': versionRelease := 461808; // 461814 before Win10 April 2018 Update
              'v4.8':   versionRelease := 528040; // 528049 before Win10 May 2019 Update
            end;
        end;
    
        // installation key group for all .NET versions
        key := 'SOFTWARE\Microsoft\NET Framework Setup\NDP\' + versionKey;
    
        // .NET 3.0 uses value InstallSuccess in subkey Setup
        if Pos('v3.0', version) = 1 then begin
            success := RegQueryDWordValue(HKLM, key + '\Setup', 'InstallSuccess', install);
        end else begin
            success := RegQueryDWordValue(HKLM, key, 'Install', install);
        end;
    
        // .NET 4.0 and newer use value Servicing instead of SP
        if Pos('v4', version) = 1 then begin
            success := success and RegQueryDWordValue(HKLM, key, 'Servicing', serviceCount);
        end else begin
            success := success and RegQueryDWordValue(HKLM, key, 'SP', serviceCount);
        end;
    
        // .NET 4.5 and newer use additional value Release
        if versionRelease > 0 then begin
            success := success and RegQueryDWordValue(HKLM, key, 'Release', release);
            success := success and (release >= versionRelease);
        end;
    
        result := success and (install = 1) and (serviceCount >= service);
    end;
    
    function InitializeSetup(): Boolean;
    begin
        if not IsDotNetDetected('v4.6', 0) then begin
            MsgBox('MyApp requires Microsoft .NET Framework 4.6.'#13#13
                'Please use Windows Update to install this version,'#13
                'and then re-run the MyApp setup program.', mbInformation, MB_OK);
            result := false;
        end else
            result := true;
    end;
    

    (取自这里的代码:http://www.kynosarges.de/DotNetVersion.html

    首先,它检查是否存在指示已安装 .NET 框架版本的注册表项。如果注册表项不存在,它会提示用户下载 .NET 框架。如果用户说是,它会打开下载 URL。 (您可能必须将它在脚本中指定的版本更改为 4.0 版。)


    我还遇到了 [this article on CodeProject][1],这可能是一种更全面、更可定制的方式来做你正在寻找的事情,尽管它可能需要更多的工作才能理解并且必须修改才能使用版本4.0。

    【讨论】:

    • 好。但我需要从本地(从我的安装应用程序)安装框架 4.0
    • 您应该能够轻松地修改上面的脚本来做到这一点。您必须下载 .NET Framework 4.0 安装程序(客户端配置文件或完整安装程序,无论您的应用程序需要什么),并将其包含在应用程序的安装媒体中。然后,从脚本中打开安装源目录中的现有安装文件,而不是去 Internet 获取安装程序。或者只是显示一条消息,要求用户这样做(“请先运行“NetFWSetup.exe”应用程序”)。
    • “请先运行“NetFWSetup.exe”应用程序” - 编程安装不是不做吗?
    • 对于那些想在安装时安装框架的人(在你完成整个向导并运行安装过程之后),不要在InitializeSetup事件中运行框架设置,它会启动在运行安装向导时立即安装框架,这对用户体验有什么问题。在[Run] 部分中使用Check 条件参数,例如this way
    • 作为上面引用的代码的作者,我想让您知道链接位置的代码已针对 .NET 4.5 进行了更新。
    【解决方案2】:

    @Cody Gray - 感谢您的解决方案。很有帮助!

    如果有人感兴趣,这里是我对他的函数使用枚举值而不是字符串的看法。此更改纯粹是个人喜好问题。该代码包含 v4.5 的更改,并且根据我的有限测试似乎可以正常工作。

    大卫

    [Code]
    
    //
    // Enumeration used to specify a .NET framework version 
    //
    type TDotNetFramework = (
        DotNet_v11_4322,  // .NET Framework 1.1
        DotNet_v20_50727, // .NET Framework 2.0
        DotNet_v30,       // .NET Framework 3.0
        DotNet_v35,       // .NET Framework 3.5
        DotNet_v4_Client, // .NET Framework 4.0 Client Profile
        DotNet_v4_Full,   // .NET Framework 4.0 Full Installation
        DotNet_v45);      // .NET Framework 4.5
    
    //
    // Checks whether the specified .NET Framework version and service pack
    // is installed (See: http://www.kynosarges.de/DotNetVersion.html)
    //
    // Parameters:
    //   Version     - Required .NET Framework version
    //   ServicePack - Required service pack level (0: None, 1: SP1, 2: SP2 etc.)
    //
    function IsDotNetInstalled(Version: TDotNetFramework; ServicePack: cardinal): boolean;
      var
        KeyName      : string;
        Check45      : boolean;
        Success      : boolean;
        InstallFlag  : cardinal; 
        ReleaseVer   : cardinal;
        ServiceCount : cardinal;
      begin
        // Registry path for the requested .NET Version
        KeyName := 'SOFTWARE\Microsoft\NET Framework Setup\NDP\';
    
        case Version of
          DotNet_v11_4322:  KeyName := KeyName + 'v1.1.4322';
          DotNet_v20_50727: KeyName := KeyName + 'v2.0.50727';
          DotNet_v30:       KeyName := KeyName + 'v3.0';
          DotNet_v35:       KeyName := KeyName + 'v3.5';
          DotNet_v4_Client: KeyName := KeyName + 'v4\Client';
          DotNet_v4_Full:   KeyName := KeyName + 'v4\Full';
          DotNet_v45:       KeyName := KeyName + 'v4\Full';
        end;
    
        // .NET 3.0 uses "InstallSuccess" key in subkey Setup
        if (Version = DotNet_v30) then
          Success := RegQueryDWordValue(HKLM, KeyName + '\Setup', 'InstallSuccess', InstallFlag) else
          Success := RegQueryDWordValue(HKLM, KeyName, 'Install', InstallFlag);
    
        // .NET 4.0/4.5 uses "Servicing" key instead of "SP"
        if (Version = DotNet_v4_Client) or
           (Version = DotNet_v4_Full) or
           (Version = DotNet_v45) then
          Success := Success and RegQueryDWordValue(HKLM, KeyName, 'Servicing', ServiceCount) else
          Success := Success and RegQueryDWordValue(HKLM, KeyName, 'SP', ServiceCount);
    
        // .NET 4.5 is distinguished from .NET 4.0 by the Release key
        if (Version = DotNet_v45) then
          begin
            Success := Success and RegQueryDWordValue(HKLM, KeyName, 'Release', ReleaseVer);
            Success := Success and (ReleaseVer >= 378389);
          end;
    
        Result := Success and (InstallFlag = 1) and (ServiceCount >= ServicePack);
      end;
    

    【讨论】:

    • 这看起来不错,但你能从检查参数中展示如何使用它吗?
    • 在上面的函数后面加上这个:function IsDotNetReallyInstalled(): Boolean; begin result := IsDotNetInstalled(DotNet_v45, 0); end; 然后在你的'check'函数中调用它。
    • 对不起...检查参数:添加'not'...不是IsDotNetInstalled
    • 你能告诉我用于检测 4.6.1 版本的注册表项名称吗?这样我就可以扩展您的代码?谢谢
    • @David 所以我已经将你的代码扩展为 4.6.1 版本 if (Version = DotNet_v4_6_1) then begin Success := Success and RegQueryDWordValue(HKLM, KeyName, 'Release', ReleaseVer);成功 := 成功并且 (ReleaseVer >= 394271);结尾;但我想知道最后一行的 InstallFlag 值 Result := Success and (InstallFlag = 1) and (ServiceCount >= ServicePack);如果传递给版本为 DotNet_v4_6_1 的函数?因为它永远不会得到一个值并且它没有被初始化。请问有什么意见吗?谢谢
    【解决方案3】:

    如果您不关心是否安装了“完整”版本或仅安装了“客户端”版本的 .NET 4:

    try
      ExpandConstant('{dotnet40}');
      // Installed
    except
      // Not installed
    end;
    

    【讨论】:

      【解决方案4】:

      感谢大家提供现有的解决方案,它们工作得很好。

      不过,我不需要支持每个框架版本,但一次只需要一个,并且没有“古老”的版本(.NET 4.0 或更早版本)。我也不需要检查服务版本。

      所以,代码变得很多更简单,我发现减少噪音更可取:

      [Code]
      // http://www.kynosarges.de/DotNetVersion.html
      
      function IsDotNetDetected(): boolean;
      var
          key: string;
          install, release: cardinal;
          success: boolean;
      begin
          key := 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full'
          
          // success: true if the registry has been read successfully
          success := RegQueryDWordValue(HKLM, key, 'Install', install);
          success := success and RegQueryDWordValue(HKLM, key, 'Release', release);
      
          // install = 1 if framework is installed
          // 461808 -> .NET 4.7.2 461814 before Win10 April 2018 Update
          // see https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed
          // for details
          result := success and (install = 1) and (release >= 461808);
      end;
      
      function InitializeSetup(): Boolean;
      begin
          if not IsDotNetDetected() then begin
              MsgBox('MyApp requires Microsoft .NET Framework 4.7.2.'#13#13
                  'Please install it and then re-run this setup program.', mbInformation, MB_OK);
              result := false;
          end else
              result := true;
      end;
      

      您只需将上面代码中的版本常量 (461808) 替换为 Microsoft 参考页面中所需的值,并相应地更新错误消息。

      【讨论】:

        【解决方案5】:

        我发现至少从 innosetup 版本 6.0.5 开始,此功能就已成为框架的一部分。因此,您不必自己编写函数代码。

        函数:IsDotNetInstalled

        这是一个简短的例子:

        [Setup]
        AppName=".NET Framwork Test"
        AppVersion=0.0.0.1
        DefaultDirName={tmp}\MyApp
        
        [Code]
        function InitializeSetup(): Boolean;
        begin
          Result := IsDotNetInstalled(net45, 0);
        
          if Result then begin
            MsgBox('Min .NET Framwork is installed', mbInformation, MB_OK);
          end else begin
            MsgBox('Min .NET Framwork is not installed', mbInformation, MB_OK);
          end;
        end;
        

        【讨论】:

          猜你喜欢
          • 2022-10-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-24
          • 2022-01-24
          • 2020-04-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多