一文看懂如何利用QtIFW制作安装包,小白也能看懂且学会的软件安装包制作教程;(本文不基于Qt工程)
安装程序生成工具就是将应用程序和依赖的文件打包到一个可执行的安装程序种,可以简化用户的安装流程和体验,但开发的软件依赖和配置过于繁杂的时候,制作一个安装包就特别必要,所以需要简单学习一下安装程序生成工具,以下是常见的安装程序生成工具:
这里不卖关子,就选择
QtIFW
,QtIFW
本身就是作为Qt项目的一部分开发的,框架本身使用Qt。然而,它可以用于安装所有类型的应用程序,包括(但不限于)使用Qt构建的应用程序。而且它是跨平台且使用XML的描述语言来配置安装程序的,所以这里选择
QtIFW
;
Qt Installer Framework(QtIFW)是一个开源的、跨平台的安装和打包工具套件,用于创建易于使用和可定制的安装程序。下面是Qt Installer Framework
的详细介绍和优势:
下载地址:https://download.qt.io/official_releases/qt-installer-framework/
版本选择:选择最新的版本即可
然后根据你的操作系统选择安装包下载;
按照安装向导去操作即可,没有坑和注意事项;
将bin目录配置到环境变量中,这里必须添加,不然后面没办法打包;
我们先不管自己的项目;
QtIFW安装后,是提供了一些示例的项目的,我们先针对某个示例项目打包,走通流程;
QtIFW安装目录\examples\startmenu
进入startmenu目录;
在该目录下打开cmd窗口;
运行打包命令(先不管具体含义,先把流程打通,后面再看具体含义):
binarycreator -c config\config.xml -p packages README
如上图,没报错就说明打包成功了;
然后在我们的项目根目录下就可以看到制作好的安装包了;
首先运行没问题
然后在开始菜单中找到README文件:
点击,就会打开这个readme文件;
大功告成啦!!!
整个的目录结构应该就是如下的一个情况:
examples/
└── startmenu/
├── config/
│ └── config.xml
├── packages/
│ └── org.qtproject.ifw.example/
│ ├── data/
│ │ └── README.txt
│ └── meta/
│ ├── installscript.qs
│ └── package.xml
├── README
└── startmenu.pro
在该结构中,startmenu
项目包含以下文件和文件夹:
config/
:包含配置文件相关的文件夹。config.xml
:定义了安装程序的设置和信息,例如安装路径、安装界面的外观、需要安装的软件包等。可以使用Qt IFW的IFWConfig工具或者手动编辑该文件。packages/
:是存放软件包及其描述文件的目录。每个软件包文件夹都包含一个或多个软件包,其结构如下:-packages
- com.vendor.root
- data
- meta
- com.vendor.root.component1
- data
- meta
- com.vendor.root.component1.subcomponent1
- data
- meta
- com.vendor.root.component2
- data
- meta
org.qtproject.ifw.example/
:示例软件包的目录。data/
:这一个存是放着软件包的安装文件的目录,这些文件将被复制到用户计算机上的目标路径。【这是最重要的目录,目标软件所有的可执行程序以及依赖等都放到这个文件夹下,QtIFW才能针对这个软件进行安装包制作】meta/
:包含安装程序的元数据文件,通常包含安装脚本文件、许可协议文件、安装程序的图标文件等等,后续在具体的配置讲解中会提到;installscript.qs
:安装脚本文件,定义了安装过程,包括安装前的准备工作、安装期间的操作以及安装完成后的清理工作等。使用IFWConfig工具创建安装程序时,会自动生成安装脚本文件;手动创建安装程序时,需要自己编写安装脚本文件。README
:项目的说明文档,包含有关项目、安装程序和开发细节的其他信息(这个文件对于QtIFW的使用是可有可无的)。startmenu.pro
:项目的Qt工程文件(后续我们不做Qt工程,这个文件可以不用管)。总结一下,根目录下两个文件夹;
config文件夹里面配置安装包的设置和信息;
packages文件夹内是一个或多个软件包;
每个软件包目录下有一个data和一个meta目录;
meta放的是安装包的元数据;
data放的是待打包的全量文件(可执行程序及依赖);
当然这个目录并不是定死的,需要根据项目实际情况进行甄别;
binarycreator -c config\config.xml -p packages README
binarycreator
:这不用多说;
-c config\config.xml
:指定配置文件config.xml
的路径;
-p packages
:指定包含要添加到安装程序的组件的目录路径。也就是指定软件包在哪里
README
:指定安装包名称;
binarycreator [options] -c config.xml -p packages path/to/output/installer
[options]
:用于指定命令的其他选项。常见的选项包括:
--platform
:指定目标平台(例如,win32-msvc2019
、mac
、linux
)。
--offline-only
:指定仅创建离线安装程序,不从互联网下载任何组件。
--online-only
:指定仅创建在线安装程序,从互联网下载所有组件。
--no-sdk
:指定不包含Qt开发工具包(SDK)。
--no-force-overwrite
:指定如果目标文件已存在,则不覆盖它。
--no-system-detection
:指定不检测系统信息。
--verbose
:显示详细的日志输出。
--help
:显示命令的帮助信息。
-c config.xml
:指定配置文件 config.xml
的路径。
-p packages
:指定包含要添加到安装程序的组件的目录路径。
path/to/output/installer
:指定生成的安装程序的输出路径和名称。可以指定一个文件路径,作为最终生成的安装程序的存储位置和名称。上面我们执行的命令中,只指定了名称,就生成在了项目根目录下;
config
目录没问题;
packages
目录就有点问题了,因为上面说了,这个目录下可以放多个软件包,那么如果有多个软件包在目录下怎么打包呢?
默认情况下,Qt Installer Framework(qtifw)不会为每个软件包生成单独的安装程序。它将所有软件包组合到一个统一的安装程序中,用户可以选择安装其中的哪些软件包。
如果要打包指定的安装包,可以在命令中指定:
binarycreator -c config.xml -p packages installer --component Package2
使用了
--component Package2
选项来指定只打包Package2软件包。另外,如果要将所有的软件包都分别打包,可以在config.xml中指定,具体使用参考后面的配置编写教程;
下图就是我们制作好的安装包默认的安装过程;
介绍页面、选择安装文件夹、选择安装的组件、许可协议、选择设置开始菜单快捷方式、安装;
也就是下图中的几个主要的步骤;
以下就是一个典型的config.xml文件内容
<Installer>
<Name>Some ApplicationName>
<Version>1.0.0Version>
<Title>Some Application SetupTitle>
<Publisher>Your CompanyPublisher>
<ProductUrl>http://www.your-fantastic-company.comProductUrl>
<InstallerWindowIcon>installericonInstallerWindowIcon>
<InstallerApplicationIcon>installericonInstallerApplicationIcon>
<Logo>logo.pngLogo>
<Watermark>watermark.pngWatermark>
<RunProgram>@TargetDir@/YourAppToRunRunProgram>
<RunProgramArguments>
<Argument>Argument 1Argument>
<Argument>Argument 2Argument>
RunProgramArguments>
<RunProgramDescription>My nice applicationRunProgramDescription>
<StartMenuDir>Some Application Entry DirStartMenuDir>
<MaintenanceToolName>SDKMaintenanceToolMaintenanceToolName>
<AllowNonAsciiCharacters>trueAllowNonAsciiCharacters>
<Background>background.pngBackground>
<TargetDir>@HomeDir@/testinstallTargetDir>
<AdminTargetDir>@RootDir@/testinstallAdminTargetDir>
<RemoteRepositories>
<Repository>
<Url>http://www.your-repo-location/packages/Url>
Repository>
RemoteRepositories>
Installer>
部分元素的简单说明如下,更多详细的内容和使用方法见官网:配置文件 |Qt安装程序框架手册
元素 | 说明 |
---|---|
Name | 要安装的产品的名称,必填项; |
Version | 要安装的产品的版本采用以下格式: [0-9]+((.|-)[0-9]+)* 例如 1-1; 1.2-2; 3.4.7;必填项. |
Title | 安装程序标题栏上显示的名称; |
Publisher | 软件的发行人(如 Windows 控制面板中所示)。 |
ProductUrl | 产品网址,指向产品信息的页面的URL。 |
InstallerApplicationIcon | 安装包图标的文件名,通过附加“.icns”(macOS)“.ico”(Windows)后缀来查找实际文件。在Unix上不适用 |
InstallerWindowIcon | 用于安装程序应用程序的自定义窗口图标的文件名,使用PNG格式。仅在Windows和Linux上使用,在macOS上不适用。 |
Logo | 标志的图片; |
Watermark | PNG格式水印的图片,如果要显示的话,需要加上
|
Banner | 横幅图片配置,但是WizardStyle必须设置为Modern |
Background | 设置背景图片,但是WizardStyle必须设置为Mac,需要保证
|
PageListPixmap | 设置左侧指引上面的图片,需要保证
|
WizardStyle | 设置向导页面的整体样式(“Modern”, “Mac”, “Aero” or “Classic”); |
StyleSheet | 设置样式表文件; |
WizardDefaultWidth | 设置向导的默认宽度(以像素为单位)。设置横幅图像将覆盖此设置; |
WizardDefaultHeight | 设置向导的默认高度(以像素为单位),设置水印图像将覆盖这一点; |
WizardMinimumWidth | 设置向导的最小宽度(以像素为单位); |
WizardMinimumHeight | 设置向导的最小高度(以像素为单位); |
WizardShowPageList | 控制是否显示左侧列出安装程序页面的小组件; |
ProductImages | 产品图片的配置; |
TitleColor | 设置标题和副标题的颜色(采用 HTML 颜色代码,例如“#88FF33”); |
RunProgram | 如果用户接受操作,则在安装程序完成后执行命令。提供应用程序的完整路径; |
RunProgramArguments | 传递给指定的程序的参数。可以添加多个子元素,每个子元素都指定一个参数; |
RunProgramDescription | 在用于在安装后运行程序的复选框旁边显示的文本。如果已设置但未提供说明,则会显示 UI; |
StartMenuDir | Windows 菜单中产品的默认程序组的名称; |
TargetDir | 用于安装的默认目标目录。在 Linux 上,这通常是用户的主目录; |
AdminTargetDir | 具有管理员权限的安装的默认目标目录。仅在 Linux 上可用,您通常不希望在管理员用户的主目录中安装; |
LocalCacheDir | 用于存储元数据缓存的目录名称。这不包括前导目录,前导目录是根据用于存储缓存文件的合适平台特定位置自动确定的。用户可以覆盖安装程序设置中的路径。默认值是根据要安装的产品的名称生成的 UUID; |
PersistentLocalCache | 设置为安装程序退出时是否应从本地缓存中删除提取的元数据。否则,将保留缓存的内容以加快后续提取速度; |
RemoteRepositories | 远程存储库列表。此元素可以包含多个子元素,每个子元素都包含指定访问存储库的 URL 的子元素。有关更多信息,请参阅配置存储库; |
RepositoryCategories | 可以包含子元素列表的类别的名称。有关更多信息,请参阅配置存储库类别; |
MaintenanceToolName | 生成的维护工具的文件名。默认为维护工具。将追加特定于平台的可执行文件扩展名; |
MaintenanceToolIniFile | 生成的维护工具配置的文件名; |
MaintenanceToolAlias | 将创建到应用程序目录的维护工具别名的文件名。自选。仅在 macOS 上使用; |
RemoveTargetDir | 设置为卸载时不应删除目标目录; |
AllowNonAsciiCharacters | 控制安装路径是否可以包含非ASCII字符; |
安装好后,windows系统可以在控制面板中查看配置的详情;
如下,更多的内容去试试就知道啦!
这是软件包信息配置文件:
<Package>
<DisplayName>QtGuiDisplayName>
<Description>Qt gui librariesDescription>
<Description xml:lang="de_de">Qt GUI BibliothekenDescription>
<Version>1.2.3Version>
<ReleaseDate>2009-04-23ReleaseDate>
<Name>com.vendor.root.component2Name>
<Dependencies>com.vendor.root.component1Dependencies>
<Virtual>falseVirtual>
<Licenses>
<License name="License Agreement" file="license.txt" />
Licenses>
<Script>installscript.qsScript>
<UserInterfaces>
<UserInterface>specialpage.uiUserInterface>
<UserInterface>errorpage.uiUserInterface>
UserInterfaces>
<Translations>
<Translation>sv_se.qmTranslation>
<Translation>de_de.qmTranslation>
Translations>
<DownloadableArchives>component2.7z, component2a.7zDownloadableArchives>
<AutoDependOn>com.vendor.root.component3AutoDependOn>
<SortingPriority>123SortingPriority>
<UpdateText>This changed compared to the last releaseUpdateText>
<Default>falseDefault>
<ForcedInstallation>falseForcedInstallation>
<ForcedUpdate>falseForcedUpdate>
<Essential>falseEssential>
<Replaces>com.vendor.root.component2oldReplaces>
<Operations>
<Operation name="AppendFile">
<Argument>@TargetDir@/A.txtArgument>
<Argument>lorem ipsumArgument>
Operation>
<Operation name="Extract">
<Argument>@TargetDir@/Folder1Argument>
<Argument>content.7zArgument>
Operation>
<Operation name="Extract">
<Argument>@TargetDir@/Folder2Argument>
Operation>
Operations>
<TreeName moveChildren="true">com.vendor.subcomponentTreeName>
Package>
:指定软件包的显示名称为"QtGui"。
:提供了一个关于软件包的描述信息,指出它是Qt图形用户界面库。
:为了国际化支持,该元素提供了一个德语版本的描述信息。
:指定软件包的版本号为"1.2.3"。
:指定软件包的发布日期为"2009-04-23"。
:指定软件包的唯一标识符为"com.vendor.root.component2"。
:指定软件包依赖的其他软件包,这里依赖"com.vendor.root.component1"。
:指示软件包是否是虚拟包,即实际上没有提供任何文件。
:定义许可证信息,这里提供了一个名为"License Agreement"的许可证文件"license.txt"。
:指定安装脚本文件为"installscript.qs"。
:定义用户界面文件,这里列出了两个界面文件"specialpage.ui"和"errorpage.ui"。
:定义翻译文件,这里列出了两个翻译文件"sv_se.qm"和"de_de.qm"。
:指定可下载的存档文件,这里有两个文件"component2.7z"和"component2a.7z"。
:指定软件包自动依赖的其他软件包,这里自动依赖"com.vendor.root.component3"。
:指定软件包的排序优先级为123。
:提供软件包更新时的文本描述,指出与上一个版本相比的更改内容。
:指示软件包是否作为默认选择。
:指示软件包是否要求强制安装。
:指示软件包是否要求强制更新。
:指示软件包是否是必需的。
:指定该软件包可以替代的旧版本软件包"com.vendor.root.component2old"。
:定义操作列表,包括"AppendFile"和两个"Extract"操作,用于在安装过程中执行特定的文件操作。
:指定组件树的名称为"com.vendor.subcomponent",并设定其子组件是否移动。官网地址:https://doc.qt.io/qtinstallerframework/scripting.html
推荐博客:http://t.csdn.cn/xrqn6
installscript.qs
是一个用于安装程序的脚本文件,它使用了Qt Installer Framework提供的安装脚本语言。在这个脚本中,可以定义需要执行的操作来完成安装过程。
function Component()
{
// 添加操作函数
function addOperation(op)
{
installer.addOperation(op);
}
// 组件名称
this.componentName = "MyApp";
// 组件版本号
this.componentVersion = "1.0.0";
// 开始安装前的初始化操作
this.installationStarted = function()
{
console.log("Installation started");
}
// 条件判断
if (systemInfo.productType === "windows")
{
// Windows平台特定操作
var startMenuDir = installer.value("StartMenuDir");
var shortcutPath = startMenuDir + "\\MyApp.lnk";
addOperation("CreateShortcut", "@TargetDir@/MyApp.exe", shortcutPath);
}
else if (systemInfo.productType === "osx")
{
// macOS平台特定操作
var applicationsDir = installer.value("ApplicationsDir");
var shortcutPath = applicationsDir + "/MyApp.app";
addOperation("CopyDirectory", "@TargetDir@/MyApp.app", shortcutPath);
}
// 结束安装后的清理操作
this.installationFinished = function()
{
console.log("Installation finished");
}
}
// 创建组件实例
var component = new Component();
componentName
和componentVersion
:用于定义组件的名称和版本号。installationStarted
:在安装开始前被调用的函数,可以用于执行一些初始化操作。systemInfo.productType
的值(表示当前的操作系统类型)进行条件判断,针对不同的平台进行不同的操作。addOperation
是一个辅助函数,用于添加操作到安装脚本中。它接收一个或多个参数,这些参数定义了需要执行的操作及其参数。installationFinished
是在安装完成后被调用的函数,可以用于执行一些清理操作。在示例中,根据平台类型执行了不同的操作。对于Windows平台,使用CreateShortcut
操作创建了一个名为MyApp.lnk
的快捷方式,指向@TargetDir@/MyApp.exe
;对于macOS平台,则通过CopyDirectory
操作将@TargetDir@/MyApp.app
复制到Applications
目录下。
可以根据实际需求,通过添加其他操作函数来执行更多的操作,如复制文件、创建目录、注册表项等。
更高级的一些操作,需要结合实际需求来看怎么配置;
下面这个是上面演示的项目的文件的代码注释:
function Component() {
// 默认构造函数
}
Component.prototype.createOperations = function() {
// 调用默认实现来安装 README.txt!
component.createOperations();
if (systemInfo.productType === "windows") {
component.addOperation(
"CreateShortcut",
"@TargetDir@/README.txt", // 快捷方式目标文件路径
"@StartMenuDir@/jmz.lnk", // 快捷方式创建位置
"workingDirectory=@TargetDir@", // 工作目录
"iconPath=%SystemRoot%/system32/SHELL32.dll", // 图标文件路径
"iconId=2", // 图标索引
"description=Open README file" // 描述信息
);
}
}
类似上面提到的结构,新建一个目录,以及一些必要的文件;
这边我创建的目录如下:
test/
└── calculator/
├── config/
│ └── config.xml
└── packages/
└── installer_1/
├── data/
│ └── 现在为空
└── meta/
├── installscript.qs
└── package.xml
就是把打包好的文件全部放到data目录下;
至于怎么打包,这里不过多叙述,可以看看我另外一篇关于python打包gui程序的博客;
<Installer>
<Name>九陌斋计算器Name>
<Version>1.0.0Version>
<Title>九陌斋计算器Title>
<Publisher>九陌斋Publisher>
<ProductUrl>https://blog.jiumoz.comProductUrl>
<InstallerApplicationIcon>faviconInstallerApplicationIcon>
<InstallerWindowIcon>app.pngInstallerWindowIcon>
<Logo>logo.pngLogo>
<TargetDir>@ApplicationsDir@/九陌斋计算器TargetDir>
<AllowNonAsciiCharacters>trueAllowNonAsciiCharacters>
<WizardStyle>MacWizardStyle>
<StartMenuDir>九陌斋计算器StartMenuDir>
Installer>
: 指定安装程序的名称为"九陌斋计算器"。
: 指定安装程序的版本号为"1.0.0"。
: 指定安装程序对话框的标题为"九陌斋计算器"。
: 指定发布者为"九陌斋"。
: 指定产品的网址为"https://blog.jiumoz.com"。
: 指定安装程序的应用图标为"favicon.ico",这里后缀要省略。
: 指定安装程序对话框的窗口图标为"app.png"。
: 指定安装程序对话框中显示的Logo为"app.png"。
: 指定安装程序的目标安装目录为"@ApplicationsDir@/九陌斋计算器",即在应用程序目录下创建一个名为"九陌斋计算器"的文件夹。
: 允许在安装程序对话框中使用非ASCII字符。
: 设置安装程序对话框的风格为"Mac",类似于 macOS 风格。
: 指定在开始菜单中创建一个名为"九陌斋计算器"的文件夹。这里我们要把要用到的文件也放到config目录下:
这里要注意一下,QtIFW里面好像所有的图片都不能用两次,比如
和
,图片其实是一个,但是也要复制重命名一下,不然会报错,没有过多的研究,知道的同学可以留言交流一下
<Package>
<DisplayName>九陌斋计算器DisplayName>
<Description>基于PySide6的简单计算器程序,还存在一些bug,敬请担待!Description>
<Version>1.0.0Version>
<ReleaseDate>2023-09-27ReleaseDate>
<Name>installer_1Name>
<Licenses>
<License name="九陌斋计算器安装协议" file="license.txt" />
Licenses>
<Script>installscript.qsScript>
Package>
: 指定软件包的显示名称为"九陌斋计算器"。
: 指定软件包的描述为"基于PySide6的简单计算器程序,还存在一些bug,敬请担待!"。
: 指定软件包的版本号为"1.0.0"。
: 指定软件包的发布日期为"2023-09-27"。
: 指定软件包的名称为"installer_1"。
: 指定软件包的许可证信息。
: 指定软件包的许可证名称为"九陌斋计算器安装协议",并指定许可证文件为"license.txt"。
: 引用安装脚本文件installscript.qs。
这里我们要新建一个协议文档放到meta目录下,并写一些简单的内容:
function Component()
{
// default constructor
}
Component.prototype.createOperations = function()
{
component.createOperations();
if (systemInfo.productType === "windows")
{
//开始菜单快捷方式
component.addOperation(
"CreateShortcut",
"@TargetDir@/calculator.exe",
"@StartMenuDir@/九陌斋计算器.lnk",
"workingDirectory=@TargetDir@",
"iconPath=@TargetDir@/favicon.ico",
"description=打开九陌斋计算器"
);
//桌面快捷方式
component.addOperation(
"CreateShortcut",
"@TargetDir@/calculator.exe",
"@DesktopDir@/九陌斋计算器.lnk",
"workingDirectory=@TargetDir@",
"iconPath=@TargetDir@/favicon.ico",
);
}
}
这段代码中包含两个快捷方式创建操作,分别是开始菜单快捷方式和桌面快捷方式。每个操作都接受相应的参数来定义快捷方式的属性,如目标文件路径、快捷方式路径、工作目录、图标路径和描述。
需要注意的是,在开始菜单快捷方式操作中,设置了一个自定义的快捷方式名称,即"九陌斋计算器.lnk"
。如果需要更改为其他名称,请将"@StartMenuDir@/九陌斋计算器.lnk"
中的字符串部分替换为所需的名称。
另外,在桌面快捷方式操作中省略了描述的设置,如果需要添加描述,可以类似开始菜单快捷方式操作那样添加"description=xxx"
参数。
这里的配置还是很简单的,就是写了两个快捷方式的添加;
其余的可以进一步跟进实际需求探索;
binarycreator -c config\config.xml -p packages 九陌斋计算器 -v
后面加-v
能查看详细日志
正常只要没报错,就打包成功了;
查看一下根目录:
nice,大功告成;
一路往下走,安装完成后查看安装情况:
快捷方式都没问题;
ok,本文到这里就结束啦,希望你有所收获,欢迎留言交流~
原文链接:https://blog.jiumoz.com/archives/xue-hui-zhe-xie-qtifw-zhi-zuo-an-zhuang-bao-bu-zai-shi-nan-ti