Inno Setup:验证是否已安装 .NET 4.0

发布于 2024-09-30 22:23:30 字数 74 浏览 0 评论 0原文

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

I have a component that requires .NET 4.0 to run, how can my Inno Setup installer verify that it is installed, and if not, prompt the user to install it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

红玫瑰 2024-10-07 22:23:30

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 Framework。如果用户选择“是”,则会打开下载 URL。 (您可能需要将脚本中指定的版本更改为版本 4.0。)

I also came across [this article on CodeProject][1], which may be a more comprehensive and customizable way of doing what you're looking for, although it may take more work to understand and will have to be modified to work with version 4.0.

The InitializeSetup function is called when the Inno Setup executable is run. Inserting this code for a custom script should do what you want:

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;

(Code taken from here: http://www.kynosarges.de/DotNetVersion.html)

First, it checks for the presence of a registry entry that indicates the version of the .NET framework that is installed. If the registry entry is not present, it prompts the user to download the .NET framework. If the user says Yes, it opens the download URL. (You may have to change the version it specifies in the script to version 4.0.)

I also came across [this article on CodeProject][1], which may be a more comprehensive and customizable way of doing what you're looking for, although it may take more work to understand and will have to be modified to work with version 4.0.

故人的歌 2024-10-07 22:23:30

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

@Cody Gray - Thanks for your solution. Very helpful!

In case anyone is interested, here is my take on his function using enumeration values instead of strings. This change is purely a matter of personal preference. The code includes the changes for v4.5 and seems to work properly based on my limited testing.

David

[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;
你又不是我 2024-10-07 22:23:30

我发现这个功能至少从 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;

I found out that this functionality has been part of the framework since at least innosetup version 6.0.5. Therefore, you do not necessarily have to code the function yourself.

Function: IsDotNetInstalled

Here is a short example:

[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;
莫相离 2024-10-07 22:23:30

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

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

If you don't care if the "Full" or just the "Client" version of .NET 4 is installed:

try
  ExpandConstant('{dotnet40}');
  // Installed
except
  // Not installed
end;
柳絮泡泡 2024-10-07 22:23:30

感谢大家提供的现有解决方案,它们效果很好。

不过,我不需要支持每个框架版本,但一次只需支持一个,并且不需要“古老”的版本(.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://learn.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 参考页面并相应地更新错误消息。

Thanks to everyone for the existing solutions, they work great.

Still, I didn't need to support every framework version, but only one at a time, and no "ancient" ones (.NET 4.0 or older). I don't need to check for service releases too.

So, the code gets a lot simpler, and I find the reduced noise preferrable:

[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://learn.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;

You just need to replace in the code above the version constant (461808) with the value you need from the Microsoft reference page and update the error message accordingly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文