如何使用 Inno Setup 安装 .NET 框架作为先决条件?
Posted
技术标签:
【中文标题】如何使用 Inno Setup 安装 .NET 框架作为先决条件?【英文标题】:How can I install .NET framework as a prerequisite using Inno Setup? 【发布时间】:2014-01-12 05:21:46 【问题描述】:我有一个类似于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 运行时?
【问题讨论】:
InnoSetup: Verify that .NET 4.0 is installed的可能重复 @stuartd,它不是重复的... 绝对不是重复 - 只是检查,我已经在做。我正在分发可执行文件并希望在尝试将下一个文件安装到 GAC 之前安装它。 (这个问题也是我链接到的问题;) 注意正确的参数是/norestart
而不是/noreboot
。
@Marc.2377 为那些不阅读 cmets 的人更新了正确的参数 ;)
【参考方案1】:
由于[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]
条目,这会导致显示停止的进度条和有关提取文件的文本。由于获取 .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 设置执行期间向导表单的样子(进度条是动画的):
【讨论】:
史诗。这完全有效 - 但是有一个奇怪的地方 - 它似乎在执行安装时挂在“提取文件”上。有什么方法可以让用户知道这里确实发生了什么事? 我添加了一个代码框架,说明如何将安装进度条转换为选取框样式,并添加了关于在 .NET 安装执行期间安装 .NET 框架的文本。设置完成后,进度条变回正常样式,文本恢复为“正在提取文件...”。 我希望我能 +2 这个。这是一个很棒的解决方案! 我没有自己做 Marque,而是为 .NET 安装程序(也是 VC++ 运行时)使用了 /passive 选项。这确实有弹出额外消息框的缺点,但它是一个稍微简单的解决方案。 添加 /q 将再次导致安装失败,遗憾的是,非常感谢,我将删除 em【参考方案2】:我只想向@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;
【讨论】:
Err,设置失败时关闭,在什么情况下?在哪里 ?主要是为什么?该问题没有询问安装失败时如何关闭向导表单。无论如何,强行关闭向导表单闻起来像是一个糟糕的 UX 想法。还是我错过了什么? 为什么?在您的代码中,即使框架安装失败,设置也会继续。不,他没有要求这样做,但如果它没有以“成功安装”结束并且用户无法执行程序,这是一个优势。不,它不会杀死安装程序。它只是将问题跳过给用户“你真的要取消吗”。 啊,我现在看到了问题。好吧,我可能应该建议从PrepareToInstall
事件安装,而不是使用AfterInstall
功能。这使您能够更优雅地退出设置。【参考方案3】:
检查 .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;
【讨论】:
你的功能很棒。如果有人在寻找其他版本的 .net,请查看此页面 docs.microsoft.com/en-us/dotnet/framework/migration-guide/… 正是我在寻找的东西,在几个小时内!非常感谢队友!注意,对于 4.7.1,最后一行应该是 and (ver 【参考方案4】:如果您不想打包到非常繁重的完整 .NET 安装程序中,也可以将其设置为下载 Web 引导程序并运行它。我写了a blog post on how to do that with Inno Download Plugin。
【讨论】:
以上是关于如何使用 Inno Setup 安装 .NET 框架作为先决条件?的主要内容,如果未能解决你的问题,请参考以下文章
Inno Setup 如何使用皮肤插件更换软件安装包界面和外框包装?望详细解答!
Inno Setup CreateProcess 失败:代码 740(Inno Setup打包的程序提升为管理员权限)