如何使用 SFX 和 HTA 创建适用于多 CPU 架构 MSI 安装程序的单一安装程序包?
解释如何为多 CPU 安装程序创建单个软件包,并根据用户机器配置运行正确的安装程序。
引言
软件部署是软件开发领域中一项复杂的任务,现在我们需要为不同的 CPU 架构(如 32 位、64 位和 Itanium)创建单独的安装程序,这增加了软件部署的复杂性。当我们为同一产品提供不同的安装程序时,最终用户通常会混淆选择正确的安装程序,因此在本文中,我们将探讨如何为多种 CPU 架构创建单个安装程序包,以及如何根据用户机器配置触发正确的安装程序。
背景
最近,我参与了一个需要部署到不同 CPU 架构的产品。最终用户希望为不同的主机应用程序和操作系统提供一个单一的安装程序,并且我们还需要在开始安装 MSI 安装程序之前执行一些自定义操作。为此,我们找到了一个使用 SFX 和 HTA 的解决方案,我们将在本文的其余部分详细介绍它,因此本文的读者应该了解如何创建存档文件、HTML/HTML 应用程序 (HTA)、JavaScript 和 VBScript。如果您对上述主题没有任何先前的知识,请阅读以下链接。
SFX
SFX 代表自解压文件。它是一个压缩的、归档的可执行文件,无需任何归档程序即可解压缩和提取内容。
大多数归档程序都支持创建 SFX 文件,有些程序则将归档文件转换为 SFX 文件。
请参阅此链接以获取更多信息。
HTA
HTA 代表 HTML 应用程序。它是一个基于 HTML 的 Windows 程序,支持 JavaScript 和 VB Script。
HTA 结构与 HTML 页面完全相同,此外它将包含 HTA 主机标签,如下所示:
<HTA:APPLICATION ID="oHTA"
APPLICATIONNAME="myApp"
BORDER="thin"
BORDERSTYLE="normal"
CAPTION="yes"
ICON=""
MAXIMIZEBUTTON="yes"
MINIMIZEBUTTON="yes"
SHOWINTASKBAR="no"
SINGLEINSTANCE="no"
SYSMENU="yes"
VERSION="1.0"
WINDOWSTATE="maximize"/>
此标签应放置在 HTML 的 header 标签下,其余部分与 HTML 类似。我们可以使用 Jscript 或 VBScript 中的任何一个脚本,或两者都使用。这是一个带有脚本的示例 HTA 文件:
<html>
<head>
<title>My First HTA Splash Screen</title>
<style type="text/css">
html, body
{
margin: 0;
padding: 0;
height: 100%;
}
body
{
background-color: #FFF;
border: 0px;
margin: 0px;
font-family: @Calibri;
background-color: LightGray;
}
#container
{
min-height: 100%;
position: relative;
}
#header
{
background-color: Lime;
}
#body
{
background-color: LightGray;
padding: 5px;
position: relative;
}
#footer
{
background-color: Gray;
position: absolute;
bottom: 0;
width: 100%;
min-height: 60px;
}
</style>
</head>
<script language="javascript" type="text/javascript">
function CloseMe() {
//CloseWindow();
window.close();
}
function ShowBrowserVersion() {
var browser = GetBrowserInfo();
alert(browser.name + " - " + browser.version);
}
function GetBrowserInfo() {
var ua = navigator.userAgent, tem, M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
if (/trident/i.test(M[1])) {
tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
return { name: 'IE', version: (tem[1] || '') };
}
if (M[1] === 'Chrome') {
tem = ua.match(/\bOPR\/(\d+)/)
if (tem != null) { return { name: 'Opera', version: tem[1] }; }
}
M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];
if ((tem = ua.match(/version\/(\d+)/i)) != null) { M.splice(1, 1, tem[1]); }
return {
name: M[0],
version: M[1]
};
}
</script>
<hta:application id="htaSplash" applicationname="Splash Screen" scroll="No" scrollflat="no"
caption="No" singleinstance="Yes" borderstyle="none" minimizebutton="No" maximizebutton="No"
showintaskbar="no" innerborder="no" border="none" />
</head>
<body>
<div id="container">
<div id="header">
<table width="100%">
<tr>
<td align="center">
Header
</td>
</tr>
</table>
</div>
<div id="body">
<table width="100%">
<tr>
<td align="center">
Body
</td>
</tr>
<tr>
<td>
<a href="#" onclick="javascript:ShowBrowserVersion();">Browser Version - Javascript</a>
</td>
</tr>
<tr>
<td>
<a href="#" onclick="vbs:SayHello">Say Hello - VBscript</a>
<br />
</td>
</tr>
<tr>
<td>
<a href="#" onclick="javascript:CloseMe();">Close</a>
<br />
</td>
</tr>
<tr>
<td>
<br />
<br />
<br />
<br />
<br />
</td>
</tr>
</table>
</div>
<div id="footer">
<table width="100%">
<tr>
<td align="center">
Footer
</td>
</tr>
</table>
</div>
</div>
<script language="VBScript" type="text/vbscript">
'Resize the window
intHeight = 250
intWidth = 500
Me.ResizeTo intWidth, intHeight
'Align window to center of the screen
Me.MoveTo (screen.width / 2) - (intWidth / 2), (screen.height / 2) - (intHeight / 2)
Sub SayHello
MsgBox "Hello World!"
End Sub
Sub CloseWindow
window.Close
End Sub
</script>
上述示例 HTA 标记的快照
有关 HTA 的更多信息,请参阅以下链接,
解决方案
经过一些研究,我们找到了一个可行的解决方案,如下所示:
- 将所有安装程序和其他所需资源归档为自解压文件。
- 创建一个实用程序来检测已安装的主机应用程序版本和操作系统位数,并在自解压完成后运行此实用程序。
- 实用程序将根据从客户端机器收集的信息运行适当的安装程序。
由于 HTA 支持 VBScript,我们几乎可以完成它所能做的所有事情。它还提供了用户界面,以显示我们的品牌、产品信息和安装指南等。
或者,如果我们不想在提取后显示 UI,我们可以使用 SFX 和 VB Script 来实现上述解决方案。
这并不是我们解决此问题的唯一解决方案,您可能会发现一些比这更好的其他解决方案(使用第三方安装工具)。在这里,我只是想分享我在产品中使用的 SFX 和 HTA 组合。
现在,是时候将我们所有的知识付诸实践了。
实现
为了实现上述解决方案,我们需要执行以下三个步骤:
- 为不同的 CPU 架构创建 MSI 安装程序。
- 创建启动画面。
- 创建 SFX。
创建 MSI 安装程序
为不同的 CPU 架构创建您的产品安装程序。我为本文示例使用了 Visual Studio 2010,您可以使用其他 MSI 创建程序。这里我不会解释如何创建 MSI 安装程序,如果您需要参考,可以参考这篇文章。
创建启动窗口
使用 HTA 创建一个启动窗口。在这里,您可以根据自己的喜好和要求进行设计,但我设计了以下启动窗口以进行演示。它包括以下功能:
- 读取操作系统详细信息。
- 读取 CPU 详细信息。
- 读取物理内存详细信息。
- 扫描先决条件(此示例中未实现,但您可以添加自己的)。
- 显示上述信息。
- 根据 CPU 架构选择适当的安装程序。
- 显示安装指南。
启动窗口源代码
<html>
<head>
<title>Installer Splash</title>
<style type="text/css">
html, body
{
margin: 0;
padding: 0;
height: 100%;
}
body
{
background-color: #FFF;
border: 0px;
margin: 0px;
font-family: @Calibri;
background-color:LightGray;
}
#container
{
min-height: 100%;
position: relative;
}
#header
{
background-color:Orange;
}
#body
{
background-color:LightGray;
padding: 5px;
position: relative;
}
#background
{
/*padding: 5px; */
background: url(images/product.png) no-repeat center center;
filter: alpha(opacity=20); /* For IE8 and earlier */
z-index:-1;
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
width: 100%;
height: 100%;
}
#footer
{
background-color:Gray;
position: absolute;
bottom: 0;
width: 100%;
min-height: 60px;
}
.pdtitle
{
padding-top: 20px;
padding-left: 10px;
color: #fff;
vertical-align: middle;
}
.copyright
{
color: #fff;
font-size: x-small;
}
.sysinfotable
{
/*background-color:#f3f4f4;*/
border: 1px solid #B5B5B5;
font-size: smaller;
}
.inforow
{
height: 30px;
}
.bodyheader
{
font-size: large;
font-weight: bold;
}
.infocaption
{
font-weight: bold;
background-color: White;
color: Orange;
}
.infovalue
{
padding-left: 2px;
}
.bottomborder
{
border-bottom: 1px #B5B5B5 solid;
}
.leftborder
{
border-left: 1px #B5B5B5 solid;
}
#installmenu a
{
color: #0066FF;
font-weight: bolder;
}
.pageVisible
{
display:block;
}
.pageInVisible
{
display:none;
}
.loading
{
padding-top:100px;
padding-left:10px;
font-size:30;
color:#7C6D5A;
font-weight:bold;
}
#pageLoading
{
width:100%;
}
</style>
</head>
<script language="javascript" type="text/javascript">
function CloseMe() {
//CloseWindow();
window.close();
}
function InstallAddin() {
Install();
}
function ShowBrowserVersion() {
var browser = GetBrowserInfo();
alert(browser.name + " - " + browser.version );
}
function GetBrowserInfo() {
var ua = navigator.userAgent, tem, M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
if (/trident/i.test(M[1])) {
tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
return { name: 'IE', version: (tem[1] || '') };
}
if (M[1] === 'Chrome') {
tem = ua.match(/\bOPR\/(\d+)/)
if (tem != null) { return { name: 'Opera', version: tem[1] }; }
}
M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];
if ((tem = ua.match(/version\/(\d+)/i)) != null) { M.splice(1, 1, tem[1]); }
return {
name: M[0],
version: M[1]
};
}
</script>
<hta:application id="htaSplash" applicationname="Installer Splash" scroll="No" scrollflat="no" caption="No"
singleinstance="Yes" borderstyle="none" minimizebutton="No" maximizebutton="No"
showintaskbar="no" innerborder="no" border="none"/>
</head>
<body>
<div id="container">
<div id="header">
<table width="100%">
<tr>
<td width="75%" valign="middle">
<h2 class="pdtitle">Product Name V1.0</h2>
</td>
<td width="25%" align="center">
<a href="http://www.yourproductsite.com"><img src="images/pdlogo.png" height="64px" border="0" alt="Product Logo" /></a>
</td>
</tr>
</table>
</div>
<div id="body">
<div id="pageLoading">
<table cellpadding="0" cellspacing="0" width="100%" height="100%" border="0">
<tr>
<td class="loading" align="center">
Loading...
</td>
</tr>
</table>
</div>
<div id="pageInfo" class="pageInVisible">
<table width="100%" border="0">
<tr>
<td class="bodyheader">
Welcome to Product
</td>
</tr>
<tr>
<td style="font-size:smaller; padding-right:10px">Product introduction here
</td>
</tr>
<tr>
<td style="font-size:small;font-weight:bold;">
System/Pre-requisites Information :
</td>
</tr>
<tr>
<td>
<table width="100%" border="0">
<tr>
<td width="70%">
<table width="100%" class="sysinfotable" border="0" cellpadding="0" cellspacing="0">
<tr>
<td class="inforow infocaption bottomborder" align="right">
Operating System :
</td>
<td class="inforow bottomborder infovalue leftborder" id="lblOS">
</td>
</tr>
<tr>
<td class="inforow infocaption bottomborder " align="right">
Processor :
</td>
<td class="inforow bottomborder infovalue leftborder altbackground" id="lblProcessor">
</td>
</tr>
<tr>
<td class="inforow infocaption bottomborder" align="right">
Phycial Memory :
</td>
<td class="inforow bottomborder infovalue leftborder" id="lblRAM">
</td>
</tr>
<tr>
<td class="inforow infocaption bottomborder" align="right">
Pre-requisites 01 :
</td>
<td class="inforow bottomborder infovalue leftborder altbackground" id="lblReq01">
</td>
</tr>
<tr>
<td class="inforow infocaption " align="right">
Pre-requisites 02 :
</td>
<td class="inforow infovalue leftborder" id="lblReq02">
</td>
</tr>
</table>
</td>
<td width="1%">
</td>
<td width="29%">
<table width="100%" cellpadding="1" cellspacing="0" id="installmenu">
<tr>
<td align="right">
<a href="#" onclick="vbs:Install" title="Click here to install the product">Install Product</a>
</td>
<td>
<a href="#" onclick="vbs:Install"><img src="images/setup.png" style="border:0px" width="32" height="32" alt="Click here to install the product"/></a>
</td>
</tr>
<tr>
<td align="right">
<a href="#" onclick="vbs:Help" title="Click here to read the installation guide">Installer Guide</a>
</td>
<td>
<a href="#" onclick="vbs:Help"><img src="images/Help.png" style="border:0px" width="32" height="32" alt="Click here to read the installation guide"/></a>
</td>
</tr>
<tr>
<td align="right">
<a href="#" onclick="javascript:CloseMe();" title="Click here to close">Exit</a>
</td>
<td>
<a href="#" onclick="javascript:CloseMe();" style="border:0px"><img src="images/close.png" style="border:0px" width="32" height="32" alt="Click here to close" /></a>
</td>
</tr>
</table>
</td>
<td width="1%">
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
<!-- replace br tags by setting dynamic hight background div tag -->
<div id="background"> <br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /></div>
</div>
<div id="footer">
<table width="100%">
<tr>
<td align="right">
<div class="copyright" id="copyright"></div>
<a class="copyright" href="http://www.yourwebsite.com">www.yourcompanywebsite.com</a>
</td>
</tr>
</table>
</div>
</div>
<SCRIPT Language="VBScript" type="text/vbscript">
Dim osBit
Dim osName,ramSize,cpuDetails,preReq01,preReq02
intHeight = 380
intWidth = 600
'Resize the main window to specific size
Me.ResizeTo intWidth, intHeight
'Align window to center of the screen
Me.MoveTo (screen.width / 2) - (intWidth / 2), (screen.height / 2) - (intHeight / 2)
'Read current machine details like OS Name, CPU details, Physical Memory and required prerequisites
Sub ReadSystemInfo
On Error Resume Next
strComputer = "."
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
strOS=""
Set colOperatingSystems = objWMIService.ExecQuery("Select * from Win32_OperatingSystem")
For Each objOperatingSystem in colOperatingSystems
strOS = objOperatingSystem.Caption
Next
osBit = 32
If Trim(strOS) <> "" Then
'Detect the CPU architecture
Set WshShell = CreateObject("WScript.Shell")
OsType = WshShell.RegRead("HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\PROCESSOR_ARCHITECTURE")
If OsType = "AMD64" then
osBit = 64
End If
End If
osName = strOS & "," & osBit & "bit"
Set colItems = objWMIService.ExecQuery("Select * from Win32_PhysicalMemory")
For Each objItem in colItems
TotalRam = TotalRam + objItem.Capacity / 1024 / 1024 / 1024
Next
ramSize = TotalRam & " GB"
Set colItems = objWMIService.ExecQuery("Select * from Win32_Processor",,48)
For Each objItem in colItems
cpuDetails = objItem.Name
Next
preReq01 = "Installed / Not Installed"
preReq02 = "Installed / Not Installed"
Set objWMIService = Nothing
Set WshShell = Nothing
End Sub
'Diplay the system information to user on the screen
Sub ShowSystemInfo
On Error Resume Next
lblOS.InnerHTML = osName
lblProcessor.InnerHTML = cpuDetails
lblRAM.InnerHTML = ramSize
lblReq01.InnerHTML = preReq01
lblReq02.InnerHTML = preReq02
pageInfo.ClassName = "pageVisible"
pageLoading.ClassName = "pageInVisible"
End Sub
'Run the appropriate addin installer based on current machine CPU architecture
Sub Install
Set objFSO = CreateObject("Scripting.FileSystemObject")
strFilePath = objFSO.GetAbsolutePathName(".")
Set objShell = CreateObject("WScript.Shell")
If osBit = 64 Then
strFilePath = strFilePath & "\Install\ProductSetup_x64.msi"
Else
strFilePath = strFilePath & "\Install\ProductSetup_x86.msi"
End if
objShell.Run strFilePath, 1, False
Set objFSO = Nothing
Set objShell = Nothing
End Sub
'Show the installation guide to user
Sub Help
Set objFSO = CreateObject("Scripting.FileSystemObject")
strFilePath = objFSO.GetAbsolutePathName(".")
Set objShell = CreateObject("WScript.Shell")
strFilePath = strFilePath & "\InstallerGuide.pdf"
'MsgBox osBit
objShell.Run strFilePath, 1, False
Set objFSO = Nothing
Set objShell = Nothing
End Sub
'Show the dynamic copyright year information
Sub ShowCopyRight
copyRight.InnerHTML = " © Your Company " & Year(Date)
End Sub
Sub CloseWindow
window.Close
End Sub
ReadSystemInfo
ShowSystemInfo
ShowCopyRight
</Script>
启动窗口快照
以下代码负责根据用户机器的 CPU 架构触发正确的安装程序。
'Detect the CPU architecture
osBit = 32
Set WshShell = CreateObject("WScript.Shell")
OsType = WshShell.RegRead("HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\PROCESSOR_ARCHITECTURE")
If OsType = "AMD64" then
osBit = 64
End If
'Run the appropriate addin installer based on current machine CPU architecture
Sub Install
Set objFSO = CreateObject("Scripting.FileSystemObject")
strFilePath = objFSO.GetAbsolutePathName(".")
Set objShell = CreateObject("WScript.Shell")
If osBit = 64 Then
strFilePath = strFilePath & "\Install\ProductSetup_x64.msi"
Else
strFilePath = strFilePath & "\Install\ProductSetup_x86.msi"
End if
objShell.Run strFilePath, 1, False
Set objFSO = Nothing
Set objShell = Nothing
End Sub
创建具有以下结构的 HTA 项目文件夹,然后将 MSI 安装程序和其他资源复制到其中。
项目文件夹
- 产品安装
- Splash.hta
- InstallerGuide.pdf
- 图像
- Close.png
- Help.png
- Pdlogo.png
- Product.png
- Setup.png
- Install
- ProductSetup_x86.msi
- ProductSetup_x64.msi
在进行下一步之前,请确保一切都已准备就绪。
创建 SFX
现在我们准备创建包含所有部署文件(包括安装程序启动文件)的自解压软件包。为此,我们需要一些特殊的程序,市场上有许多 SFX 创建器,但我们将使用两个开源应用程序来完成任务,它们是:
- 7 Zip 文件管理器 - 以 .7z 格式创建存档文件。
- 7 Zip SFX Maker - 为 7 Zip 存档创建自解压文件。
首先,我们需要使用 7 Zip 文件管理器创建存档文件,然后我们需要使用 7 Zip SFX Maker 创建自解压文件。它需要以下步骤才能获得最终输出。
- 从这里安装 7 Zip 文件管理器。如果您的机器上已安装,请跳过此步骤。
- 使用以下项目创建 7 Zip 存档文件,
- Splash.hta
- 图片文件夹
- 安装文件夹
- InstallerGuide.pdf
- 您可以随意命名存档文件,但在这里我们将其命名为 Productsetup.7z
- 从此处安装 7 Zip SFX Maker。如果您的机器上已安装,请跳过此步骤。
- 打开 7 Zip SFX Maker。
- 7 Zip SFX Maker 包含五个重要的选项卡,它们是,
- 文件选项卡 - 我们需要在此处添加 7 zip 存档文件。
- 对话框选项卡 - 它包含用于提取器各种状态的 UI 配置。
- 图标 - 其中包含提取器的图标列表,我们可以在此处为自解压 exe 选择我们的图标。
- 任务 - 我们可以在此处指定提取完成后需要执行的操作,它允许以下操作类型:
- 创建快捷方式
- 运行程序
- 删除文件或文件夹
- 设置环境变量
- 元数据 - 其中包含标准文件属性,我们可以在此处更改它们的值。
- 转到文件选项卡,单击加号按钮添加 7 zip 存档文件,它将显示文件打开对话框。
- 从硬盘中选择 productsetup.7z,然后单击“打开”按钮。
- 现在我们可以看到所选文件已添加到文件列表框中。您可以重复步骤 7 到 8 以添加更多文件。
- 转到“对话框”选项卡并执行以下操作,
- 将默认标题更改为您的自定义标题,这里我们将其命名为“产品设置”。
- 根据您的需要选择覆盖模式。默认设置为“覆盖所有文件”,在我们的示例中保留默认值。
- 我们可以设置预定义文件夹或临时文件夹来提取归档文件,并在我们的示例中选择提取到临时文件夹选项。
- 如果您想要基于 Windows XP 的 UI 主题,请选择使用 XP 样式,并在我们的示例中选择此选项。
- 如果您想减小文件大小,请选择使用 UPX 压缩 SFX 存根,UPX 提供出色的压缩比。在我们的示例中选择此选项。
- 如果您想删除提取器 exe,请选择提取后删除 SFX 文件,在我们的示例中不要选择此选项。
- 如果您想隐藏标题栏中的图标,请选择在所有窗口标题栏中隐藏图标,并在我们的示例中选择此选项。
- 如果您希望在提取的每个状态都显示提示,请选择在开始、完成和取消提示中显示 SFX 图标,在我们的示例中不要选择此选项。
- 转到所有子选项卡并进行适当的设置。
- 在我们的示例中,我们有兴趣根据当前机器的 CPU 架构和操作系统触发相应的 MSI 安装程序,因此我们应该隐藏除 HTA 启动窗口之外的所有自解压 UI。遍历所有对话框选项卡并取消选中所有子选项卡中给出的复选框(如快照所示)。
- 转到“图标”选项卡并从列表中选择您的图标。如果您对现有列表不满意,请执行以下步骤将自定义图标添加到您的自解压文件中。
- 单击“文件”->“保存设置”菜单或屏幕底部的“保存设置…”按钮。
- 它将显示“保存文件”对话框,在此处输入您的名称,在我们的示例中将其命名为 Product.xml。
- 转到 Prodcut.xml 文件夹并使用任何 xml/文本编辑器打开它。
- 转到 Settings -> General -> Icon 标签,在这里您可以设置自定义图标文件的路径(.ico 文件的路径)。
- 保存设置文件并通过 7 Zip SFX Maker 打开更新后的文件。确保“允许用户更改路径”选项在“对话框”->“提取路径”选项卡下未选中。此应用程序存在一个错误,无论何时我们打开任何保存的设置文件,指定的选项都会设置为默认值。
- 转到“任务”选项卡并单击加号按钮,添加一个在提取完成后执行的任务。请执行以下操作以在提取后显示我们的 HTA 启动窗口,
- 点击“添加”按钮。
- 它将显示新的任务选项窗口,在这里您选择“运行程序”选项。
- 它将显示“运行程序”选项窗口并输入以下详细信息。
- 在“程序”文本框末尾输入 Splash.hta。
- 选择“不等待程序完成”选项。
- 选择“隐藏控制台窗口”选项。
- 最后点击“确定”按钮。
- 现在您可以在任务列表框中看到一个条目。
- 转到“元数据”选项卡,选择每个属性并根据您的需要更改值。
- 再次保存设置。
- 点击“创建 SFX”。
- 构建成功后,状态栏上将显示“完成”消息。
- 我们的示例几乎完成,现在我们将测试输出。
- 转到 Product Setup 文件夹,您可以在此处找到一个名为 ProductSetup.sfx.exe 的自解压 exe 文件。
- 双击 ProductSetup.sfx.exe,它将 ProductSetup.7z 提取到临时文件夹并在提取后启动 Splash.hta。
- 加载 splash.hta 时,扫描系统信息,如操作系统、CPU 和物理内存以及自定义先决条件信息,并将其显示在屏幕上。
- 点击“安装产品”,启动窗口将根据操作系统位数运行相应的 MSI 安装程序。
- 单击“安装程序指南”以查看安装程序指南,以便用户在开始安装之前可以仔细阅读。
正如我们所期望的,我们得到了一个单一的安装程序包,它帮助用户根据其机器配置运行正确的安装程序,并且它还方便我们在每次安装期间向用户显示我们的品牌和产品信息。
结论
在本文中,我们探讨了如何为多种 CPU 架构的 MSI 安装程序创建单个软件包,希望它能为您提供一些有用的信息。请在评论区提供您的宝贵反馈。