如何使用Inno安装程序安装.NET framework作为先决条件?

vvppvyoh  于 2023-01-22  发布在  .NET
关注(0)|答案(5)|浏览(173)

我有一个类似于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运行时 * 之前 * 我尝试注册我的文件?

yvgpqqbh

yvgpqqbh1#

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

如果[Files]部分的.NET安装条目的Check函数的计算结果为True,则该过程很简单(FrameworkIsNotInstalled),处理该条目,将安装程序二进制文件复制到Inno Setup的临时文件夹中,如果成功,则立即调用AfterInstall函数InstallFramework。在该函数内部,通过调用Exec函数手动执行.NET安装程序。
最后,如果所有这些操作都成功了,安装程序将继续处理下一个[Files]节条目,这是要注册的程序集。现在,安装了.NET框架。如您所见,[Files]节条目的顺序在这里至关重要。
您在评论中还询问了如何向用户显示一些进度,因为按照我在这里发布的方式执行.NET安装程序会阻塞[Files]条目,这会导致显示停止的进度条和有关解压缩文件的文本。我只想在安装执行过程中向用户显示无尽的进度条。
要做到这一点,请将安装程序执行封装到如下代码中:

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安装程序执行期间向导窗体的外观(进度条是动画的):

jgwigjjp

jgwigjjp2#

我只想在@TLama上加点东西:当安装失败时关闭。这并不容易,因为WizardForm.Close;只调用了cancel-button,用户可以中止它。最后,代码看起来像这样:

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

8iwquhpp3#

我在检查.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;
dfddblmv

dfddblmv4#

如果你不想打包到非常重的完整.NET安装程序中,你也可以设置它下载web Bootstrap 并运行它。

zzoitvuj

zzoitvuj5#

我知道这是一个老职位,但由于我与Inno安装在我目前的位置,我只是想分享我的2美分.根据Inno安装文档的执行(ExpandConstant)“如果指定的文件执行成功,则返回True,否则返回False”问题是,什么是“文件已成功执行”?我目前正在处理VS++ 2019 Redist. premissions,执行@TLama示例时一切正常,除了VS++ 2019实际上根本没有安装。运行VS++ 2019 redist exe文件指定“安装失败”,因为“已经安装了此产品的另一个版本”。所以回到我之前的问题,什么是“文件执行成功”?似乎文件执行并不意味着安装程序返回退出代码0,当我记录ResultCode时,我没有得到0,但是还有一些其他的退出代码,所以我认为除了运行try if not Exec(ExpandConstant...部分之外,还值得添加另一个if ResultCode <> 0语句:

try
    if not Exec(ExpandConstant('{tmp}\vc_redist_x64_2019.exe'), '/q', '', 
    SW_SHOWNORMAL,
    ewWaitUntilTerminated, ResultCode)
    then
    begin
        MsgBox('Microsoft Visual C++ 2019 Redistributable (x64) installer failed to 
        run!' + #13#10 +
       SysErrorMessage(ResultCode), mbError, MB_OK);
   end
    else begin
        if  ResultCode <> 0 then
        begin
            MsgBox('Microsoft Visual C++ 2019 Redistributable (x64) installer failed 
            to run!' + #13#10 + SysErrorMessage(ResultCode), mbError, MB_OK);
        WizardForm.Close;
        end
  //log('the reuslt code is' + IntToStr(ResultCode))
  end;
  finally
    WizardForm.StatusLabel.Caption := StatusText;
    WizardForm.ProgressGauge.Style := npbstNormal;
  end;

我只想补充一点,我们使用的是旧的Inno安装版本(5.6.1),所以不确定新版本是否也会处理退出代码。

相关问题