如何使用InnoSetup安装.NET框架作为先决条件?

时间:2013-12-23 23:42:00

标签: .net inno-setup

我有一个类似Inno Setup: Verify that .NET 4.0 is installed的问题,但似乎略有不同。

[Files]
Source: "dependencies\dotNetFx40_Full_x86_x64.exe"; DestDir: {tmp}; Flags: deleteafterinstall; Check: FrameworkIsNotInstalled
Source: "C:\Windows\Microsoft.NET\assembly\GAC_MSIL\MySql.Data\v4.0_6.5.4.0__c5687fc88969c44d\MySql.Data.dll"; DestDir: "{app}\lib"; StrongAssemblyName: "MySql.Data, Version=6.5.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, ProcessorArchitecture=MSIL"; Flags: "gacinstall sharedfile uninsnosharedfileprompt"

[Run]
Filename: {tmp}\dotNetFx40_Full_x86_x64.exe; Description: Install Microsoft .NET Framework 4.0; Parameters: /q /norestart; Check: FrameworkIsNotInstalled

[code]
function FrameworkIsNotInstalled: Boolean;
begin
  Result := not RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\Microsoft\.NETFramework\policy\v4.0');
end;

如您所见,我正在尝试向GAC注册文件。不幸的是,在某些机器上,.NET框架可能安装。所以我需要先安装它。无论如何我可以在之前强制安装.NET运行时我尝试注册我的文件吗?

4 个答案:

答案 0 :(得分:55)

由于在[Run]部分之后处理了[Files]部分,因此使用您显示的脚本(因此您的问题)自然无法做到这一点。我建议使用的方法是从设置条目本身的AfterInstall参数函数执行.NET设置。因此,您将删除当前的[Run]部分并编写如下脚本:

[Files]
Source: "dependencies\dotNetFx40_Full_x86_x64.exe"; DestDir: {tmp}; Flags: deleteafterinstall; AfterInstall: InstallFramework; Check: FrameworkIsNotInstalled
Source: "C:\Windows\Microsoft.NET\assembly\GAC_MSIL\MySql.Data\v4.0_6.5.4.0__c5687fc88969c44d\MySql.Data.dll"; DestDir: "{app}\lib"; StrongAssemblyName: "MySql.Data, Version=6.5.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, ProcessorArchitecture=MSIL"; Flags: gacinstall sharedfile uninsnosharedfileprompt

[Code]
procedure InstallFramework;
var
  ResultCode: Integer;
begin
  if not Exec(ExpandConstant('{tmp}\dotNetFx40_Full_x86_x64.exe'), '/q /norestart', '', SW_SHOW, ewWaitUntilTerminated, ResultCode) then
  begin
    { you can interact with the user that the installation failed }
    MsgBox('.NET installation failed with code: ' + IntToStr(ResultCode) + '.',
      mbError, MB_OK);
  end;
end;

该过程很简单,如果Check部分的.NET设置条目的[Files]函数评估为True(FrameworkIsNotInstalled),则处理该条目,复制设置二进制到Inno Setup的临时文件夹中,如果成功,则会立即调用AfterInstall函数InstallFramework。在此函数内部,通过调用Exec函数手动执行.NET设置。

最后,如果所有这些都成功,安装将继续处理下一个[Files]部分条目,这是您要注册的程序集。现在,使用已安装的.NET框架。正如您所看到的,[Files]部分条目的顺序在这里至关重要。


您还在评论中另外询问了如何向用户显示一些进展,因为以我在此处发布的方式执行.NET设置会阻止[Files]条目,这会导致显示已停止有关提取文件的进度条和文本。由于获取.NET安装程序的安装进度并不容易,因此我只是在设置执行期间向用户显示无限的选取框进度条。

为此,将设置执行包装成如下代码:

procedure InstallFramework;
var
  StatusText: string;
begin
  StatusText := WizardForm.StatusLabel.Caption;
  WizardForm.StatusLabel.Caption := 'Installing .NET framework...';
  WizardForm.ProgressGauge.Style := npbstMarquee;
  try
    { here put the .NET setup execution code }
  finally
    WizardForm.StatusLabel.Caption := StatusText;
    WizardForm.ProgressGauge.Style := npbstNormal;
  end;
end;

这是.NET设置执行期间向导表单的样子(进度条是动画的):

enter image description here

答案 1 :(得分:9)

我只想在@TLama中添加一些内容:安装失败时关闭。 这并不容易,因为WizardForm.Close;只是调用取消按钮,可以被用户中止。最后,代码看起来像这样:

[Code]
var CancelWithoutPrompt: boolean;

function InitializeSetup(): Boolean;
begin
  CancelWithoutPrompt := false;
  result := true;
end;

procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);
begin
  if CurPageID=wpInstalling then
    Confirm := not CancelWithoutPrompt;
end;

function FrameworkIsNotInstalled: Boolean;
begin
  Result := not RegKeyExists(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full');
end;

procedure InstallFramework;
var
  StatusText: string;
  ResultCode: Integer;
begin
  StatusText := WizardForm.StatusLabel.Caption;
  WizardForm.StatusLabel.Caption := 'Installing .NET framework...';
  WizardForm.ProgressGauge.Style := npbstMarquee;
  try
      if not Exec(ExpandConstant('{tmp}\dotNetFx45_Full_asetup.exe'), '/q /norestart', '', SW_SHOW, ewWaitUntilTerminated, ResultCode) then
  begin
    // you can interact with the user that the installation failed
    MsgBox('.NET installation failed with code: ' + IntToStr(ResultCode) + '.',
      mbError, MB_OK);
    CancelWithoutPrompt := true;
    WizardForm.Close;       
  end;
  finally
    WizardForm.StatusLabel.Caption := StatusText;
    WizardForm.ProgressGauge.Style := npbstNormal;
  end;
end;

答案 2 :(得分:6)

检查.NET Framework 4.7只需2美分,适合@ Snicker的答案:

function FrameworkIsNotInstalled: Boolean;
var
  ver: Cardinal;
begin
  Result :=
    not
    (
    (RegKeyExists(
      HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Client')
    and
        RegQueryDWordValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Client', 'Release', ver)
    )
    or
    (RegKeyExists(
      HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full')
    and
        RegQueryDWordValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full', 'Release', ver)
    )
    )
    and (ver < 460798)
end;

答案 3 :(得分:0)

如果您不想打包在非常笨重的完整.NET安装程序中,也可以将其设置为下载Web引导程序并运行它。我写了a blog post on how to do that with Inno Download Plugin