使用WiX创建Windows应用安装包 - -YADA

news/2025/11/12 21:24:59/文章来源:https://www.cnblogs.com/yada/p/19215267

参考:官方教程

WiX 工具集(简称 WiX)用于构建 Windows 安装程序,它是构建工具、运行时工具和库的集合,不只是制作基本的安装包,还可以安装IIS网站、创建SQL Server、在Windows防火墙中注册例外。

安装 Wix 工具集

  • 无Visual Studio:用命令行安装 Wix 工具集。

    dotnet tool install --global wix
    
  • 有Visual Studio:安装 HeatWave for VS2022 扩展。安装后,重启 Visual Studio,你将看到可用的新项目模板。


添加MSI Package项目

添加 Wix 安装项目。在 解决方案资源管理器 中右键单击解决方案,然后选择“ 添加新 > 项目

image

选择MSI Package,下一步,命名项目为<产品名称>.Installer


WiX项目介绍

HeatWave中的 MSI Package (WiX v4) 模板给出了4个文件:

  • Package.wxs
  • Folders.wxs
  • ExampleComponents.wxs
  • Package.en-us.wxl

文件扩展名

HeatWave为我们生成的文件有两个扩展:

  • .wxs : WiX源文件。
  • .wxl : WiX本地化文件。

Package.wxs文件

WiX源文件是XML文件,根元素就是WiX,命名空间是 http://wixtoolset.org/schemas/v4/wxs。所有WiX源文件的根元素和命名空间都是相同的。

Package元素

Package元素表示MSI包,只能有一个Package元素。HeatWave模板填写了所有MSI包所必需的属性,例如:

<Package Id="TODO_Manufacturer.Installer" Name="Installer" Manufacturer="TODO Manufacturer" Version="1.0.0.0">
  • Id 属性设置包的全球唯一ID,建议以公司名称作为前缀。在新开发项目中用此属性代替UpgradeCode,不再手动设置UpgradeCode
  • Name 属性设置包的名称。该名称是在Windows Installed apps 列表中显示的名称。
  • Manufacturer 属性设置软件的公司的名称。此字符串也显示在Windows Installed apps 列表中。
  • Version 属性设置包的版本。包版本是管理包升级的重要部分。

MajorUpgrade元素

<MajorUpgradeDowngradeErrorMessage="!(loc.DowngradeError)" />

当你安装一个更高的版本时,之前的版本会首先被删除。

  • DowngradeErrorMessage 属性指定一个消息,当用户试图安装一个比已经安装的版本低的版本时显示。!(loc.DowngradeError) 语法是对本地化字符串的引用。
  • AllowSameVersionUpgrades 属性设置为no(默认)时,具有相同版本和UpgradeCode,但产品代码不同(产品代码每次构建时自动更新)的产品被视为两个不同产品,将被安装为两个应用。当设置为yes时,将被视为同一个产品,重复安装将视为升级。
  • IgnoreLanguage 属性设置为no(默认)时,不同语言的安装包将被安装为不同应用,设置为yes时,安装不同语言安装包将被视为升级。

Feature元素

Feature元素表示控制安装的内容。

<Feature Id="Main"><ComponentGroupRef Id="ExampleComponents" />
</Feature>

ComponentGroupRef元素

ComponentGroupRef元素表示引用具有相同Id的ComponentGroup元素,等同于把ComponentGroup元素填充到Feature元素。

另一种引用方式是通过属性引用,例如ComponentGroup元素有一个Directory属性,它的值是所引用的Directory元素的ID,表示Directory元素指定的目录作为组件组中所有文件的父目录。

<ComponentGroup Id="ExampleComponents" Directory="INSTALLFOLDER">

Folders.wxs文件

Fragment元素

Fragment元素中的内容用于被引用。单个 .wxs 文件中可以包含多个 Fragment

StandardDirectory元素

<StandardDirectory Id="ProgramFiles6432Folder">

StandardDirectory 元素使示标准目录之一作为包目录的父目录,通过Id属性指定标准目录,可用的ID参考,其中有些是MSI系统文件夹属性ID,而有些不是,例如ProgramFiles6432Folder,它会根据安装包的位数变为标准MSI目录,例如,对于32位包,将解析为ProgramFilesFolder,对应路径C:\Program Files (x86),对于64位包,将解析为ProgramFiles64Folder,对应路径C:\Program Files

Directory 元素

<Directory Id="INSTALLFOLDER"Name="!(bind.Property.Manufacturer) !(bind.Property.ProductName)" />

Directory 元素将创建一个新目录:

  • Id属性指定被引用时的ID。
  • Name是目录的名称。
  • !(bind.Property.Manufacturer)表示引用Package 元素的Manufacturer属性。
  • !(bind.Property.ProductName)表示Package 元素的Name属性。

等效于:

<Directory Id="INSTALLFOLDER"Name="TODO Manufacturer WixTutorialPackage" />

ExampleComponents.wxs文件

File元素

表示一个文件。

<File Source="ExampleComponents.wxs" />
  • Source属性指定文件的名称。
  • 示例项目是把自身的ExampleComponents.wxs文件当作安装文件,实际需改成应用程序。

Package.en-us.wxl文件

这是一个本地化文件,可以添加多个本地化文件。

<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="en-US"></WixLocalization>
  • 由于本地化文件不是 WiX 源文件,因此它们使用不同的根元素和命名空间。
  • Culture 属性指定本地化使用的语言和区域。
<String Id="DowngradeError" Value="A newer version of [ProductName] is already installed." />
  • 本地化文件主要包含一堆字符串。每个字符串都有一个 id 和一个值,该值是指定的区域性中本地化的字符串。

支持在任何硬编码字符串的地方引用本地化字符串,例如,在 Package.wxs 中使用 DowngradeError 字符串为 MajorUpgrade 元素提供错误消息:

<MajorUpgradeDowngradeErrorMessage="!(loc.DowngradeError)" />

实操

以下例子为MyApplication项目创建安装包:

image

对需要生成安装包的项目创建发布:

image

添加项目引用

在MSI Pachage项目中,添加对 MyApplication 项目的引用。右键单击 解决方案资源管理器中的安装项目,然后选择“ 添加 > 项目引用”。

项目现在应包括一个 ProjectReference 元素,如下所示:

<Project Sdk="WixToolset.Sdk/6.0.0"><ItemGroup><ProjectReference Include="..\MyApplication\MyApplication.csproj" /></ItemGroup>
</Project>

添加项目引用起到以下作用:

  • 确保应用项目在包项目之前生成,以便在生成包时应用本身可用。
  • 为包项目提供某种方法来查找应用项目的输出。

修改Package文件

修改Package元素的Id属性Name属性和Manufacturer属性。

嵌入Cabinet 文件

MSI Package项目构建后生成三个文件:

  • cab1.cab
  • WixTutorialPackage.msi
  • WixTutorialPackage.wixpdb

.cab是一个Cabinet 文件,包含了被安装的程序,与.msi文件组成了.msi包。.wixpdb文件与.pdb 文件一样,是一个调试文件,不是实际.msi包输出的一部分,可以被忽略。

WiX 的默认设值是将 cabinet 文件保持在 .msi 文件的外部,改变设置可以将 cabinet 文件嵌入到 .msi 文件本身中。在 WiX 中,MediaTemplate 元素控制如何生成和嵌入cabinet文件。在Package元素中添加MediaTemplate 元素,并设置EmbedCab属性为yes,如下所示:

<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"><PackageId="EdgerockConcepts.WixTutorialPackage"Name="WixTutorialPackage"Manufacturer="Edgerock Concepts"Version="1.0.0.0"><MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)" AllowSameVersionUpgrades="yes"IgnoreLanguage="yes"/><MediaTemplate EmbedCab="yes" /><Feature Id="Main"><ComponentGroupRef Id="AppComponents" /></Feature></Package>
</Wix>

重命名ExampleComponents

ExampleComponents是模板的示例,应该重命名为合适的名称。

以下位置需要重命名:

  • ExampleComponents.wxs重命名为AppComponents.wxs

  • 打开AppComponents.wxs文件,将ComponentGroup的ID修改为AppComponents

    <ComponentGroup Id="AppComponents" Directory="INSTALLFOLDER">
    
  • 打开Package.wxs文件,更新 ComponentGroupRef 的 ID:

    <Feature Id="Main"><ComponentGroupRef Id="AppComponents" />
    </Feature>
    

修改安装文件引用

打开AppComponents.wxs文件,修改内容如下:

<Component><File Source="MyApplication.exe" />
</Component>

WiX为每个引用项目的输出目录添加到绑定路径,绑定路径是 WiX 搜索打包的文件的路径。因此只需填写应用程序文件名,而不用填详细路径。

虽然不需要,但也可以指定绝对路径或相对路径,并且可以使用WiX预处理器变量引用具有相同名称的MSBuild 属性。例如以下示例中的$(Configuration)根据不同的解决方案配置获得路径:

<Component><File Source="..\MyApplication\bin\$(Configuration)\MyApplication.exe" />
</Component>

Configuration是一个预处理器变量。

File元素只添加单个文件。通常应用程序包含多个文件,添加多个文件需使用Files元素,如下:

<ComponentGroup Id="AppComponents" Directory="INSTALLFOLDER"><?define PublishDir = "$(MyApplication.ProjectDir)\bin\Release\net8.0\publish" ?><Files Include="$(PublishDir)\**" />
</ComponentGroup>

如果要保留某个文件卸载时不删除,比如配置文件,通过给Component元素添加Permanent="yes",表明此Component卸载时不被删除:

<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"><Fragment><ComponentGroup Id="AppComponents" Directory="INSTALLFOLDER"><?define PublishDir = "$(MyApplication.ProjectDir)\bin\Release\net8.0\publish" ?><Files Include="$(PublishDir)\**"><Exclude Files="$(PublishDir)\appsettings.json"/></Files><Component Permanent="yes"><File Source="$(PublishDir)\appsettings.json" /></Component></ComponentGroup></Fragment>
</Wix>

安装为服务

添加NuGet包:

  • WixToolset.Util.wixext

image

修改AppComponents.wxs文件。示例:

<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util"><Fragment><ComponentGroup Id="AppComponents" Directory="INSTALLFOLDER"><?define PublishDir = "$(MyApplication.ProjectDir)\bin\Release\net8.0\publish" ?><Files Include="$(PublishDir)\**"><Exclude Files="$(PublishDir)\appsettings.json"/><Exclude Files="$(PublishDir)\MyApplication.exe"/></Files><Component Permanent="yes"><File Source="$(PublishDir)\appsettings.json" /></Component><Component><File Source="$(PublishDir)\MyApplication.exe" KeyPath="yes"/><!-- Tell WiX to install the Service --><ServiceInstall Id="ServiceInstaller"Type="ownProcess"Name="!(bind.Property.ProductName)"DisplayName="!(bind.Property.ProductName)"Description="A service."Start="auto"ErrorControl="normal" ><util:ServiceConfig FirstFailureActionType="restart"SecondFailureActionType="restart"ThirdFailureActionType="restart"RestartServiceDelayInSeconds ="10" /></ServiceInstall><!-- Tell WiX to start the Service --><ServiceControl Id="StartService"Start="install"Stop="both"Remove="uninstall"Name="!(bind.Property.ProductName)"Wait="true" /></Component></ComponentGroup></Fragment>
</Wix>

缺少官方教程,以上是个人尝试出的可行方法:

  • 使用Exclude排除掉主程序文件,以便在后面的Component指定主程序文件。
  • 主程序文件使用KeyPath="yes",以便自动生成GUID
ServiceInstall

主要配置参数:

  • Startrequired

    确定何时启动服务。该属性的值必须是下列值之一:

    • auto:服务将在系统启动期间启动。
    • demand:当服务控制管理器调用 StartService 函数时,服务将启动。
    • disabled:服务不能再启动。
util:ServiceConfig

此元素是Util扩展中的元素,需要添加NuGet包:WixToolset.Util.wixext,并添加命名空间:http://wixtoolset.org/schemas/v4/wxs/util

  • FirstFailureActionType:第一次失败时的操作

  • SecondFailureActionType:第二次失败时的操作

  • ThirdFailureActionType:后续失败时的操作

    可取以下值:

    • none:无操作(默认值)
    • reboot:重新启动计算机
    • restart:重新启动服务
    • runCommand:运行一个程序
  • RestartServiceDelayInSeconds:如果三个*ActionType属性中的任何一个是“restart”,则指定在执行此操作之前等待的秒数。

修改安装路径

如果需要修改安装路径,例如建立两层文件夹,修改Folders.wxs,示例如下:

<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"><Fragment><StandardDirectory Id="ProgramFiles6432Folder"><Directory Id="ROOTDIRECTORY" Name="!(bind.Property.Manufacturer)"><Directory Id="INSTALLFOLDER" Name="!(bind.Property.ProductName)" /></Directory></StandardDirectory></Fragment>
</Wix>

生成安装包

先对被安装的项目执行发布。

然后对安装包项目执行生成,将生成一个msi文件。


进阶

阻止包安装

假如要检测安装包是否在 Windows 的 Server 版本上运行,如果是,则显示一条消息并退出安装程序。Windows Installer 可以为我们做以上事。

属性

MSI 具有许多内置属性 ,这些属性允许我们检测运行包的 Windows 版本,以及一个名为 launch conditions 的工具,用于在不满足用户指定的条件时阻止包。

MsiNTProductType 属性具有以下值:

Value Meaning
1 Windows 2000 Professional and later
2 Windows 2000 domain controller and later
3 Windows 2000 Server and later

所以如果MsiNTProductType 属性不是1,则表明在WIndows Server上运行。

条件和表达式

Windows Installer的表达式语法类似Basic,相等运算符是=,不等运算符是<>。但WiX 语言是用 XML 表示的,<> 字符是特殊的,仅用于将元素的名称括起来,不能在其他地方使用它们,因此<>要改成使用&lt;&gt;。对于MsiNTProductType <> 1,要写成MsiNTProductType &lt;&gt; 1

编写启动条件

启动条件由Launch元素表示,该元素通常作为Package 元素的子元素。

<Launch Condition="" Message="" />

如果Condition属性中的条件表达式为false,则表明不满足启动条件,将弹出一个消息框,显示Message属性的内容。

例如:

<Launch Condition="MsiNTProductType = 1" Message="Launch Condition Failed Message Goes Here" />

MsiNTProductType不为1,将弹出如下消息框:

image

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/963779.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学生信息管理系统团队项目随笔

一、团队基本信息这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/Class34Grade23ComputerScience这个作业要求在哪里 https://edu.cnblogs.com/campus/gdgy/Class34Grade23ComputerScience/homework/13481…

Total Recall: 如何在Windows下开发输入法

https://github.com/KunYi/W2K_DDK_SAMPLES/archive/refs/heads/main.zip 链接: https://pan.baidu.com/s/1Dw4SZSZUY-lrAiBWTtP_5w 提取码: enjcW2K_DDK_SAMPLES-main/ime/chs下的文件: candd.bmp canddp.bmp cande.…

大数据量场景下的编辑 / 选择 / 详情优化

面对企业系统中主子表页面的卡顿难题,需以全链路“按需”设计破局:通过前端差异提交、后端批量处理与数据层协同,将性能优化内化为无缝的用户体验,让海量数据操作变得举重若轻。在企业级系统开发中,最容易卡顿、超…

简化Python数据结构初始化:从繁琐到优雅的进阶指南 - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

RabbitMQ相关

RabbitMQ的AMQP协议是什么 AMQP(Advanced Message Queuing Protocol),高级消息队列协议,提供统一消息服务的开放标准,其核心目标是实现客户端与消息服务之前的高效、安全异步通信,并且在传递的时候不受客户端和开发…

第八天 测试用例编写

一、微信发红包xmind图二、高效编写测试用例的实用技巧 1、用例的来源:公司模板、自己设计、用例管理工具(如禅道) 2、核心字段:用例编号、用例标题、前置条件、用例步骤、预期结果、优先级 3、注意点: (1)用例…

软工团队作业2--需求规格说明书

作业信息这个作业属于哪个课程 首页 - 计科23级34班 - 广东工业大学 - 班级博客 - 博客园这个作业要求在哪里 团队作业2-《需求规格说明书》 - 作业 - 计科23级34班 - 班级博客 - 博客园这个作业的目标 明确团队项目细…

没用的博客园页面的要素介绍

rt1. 关于那几行字点击查看"<b style=color:rgb(119, 248, 255)>又是一年雨季</b>","<b style=color:rgb(119, 248, 255)>青苔悄悄爬满缝隙</b>","<b style=colo…

使用NVIDIA TAO 6和DeepStream 8构建实时视觉检测管道 - 实践

使用NVIDIA TAO 6和DeepStream 8构建实时视觉检测管道 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Cons…

ChatBI 重构工业数据交互:TDengine IDMP 让数据对话更智能

在工业数据处理领域,传统的 BI 工具往往需要用户具备专业的数据分析技能,通过复杂的操作才能获取所需信息,这在快节奏的工业生产中显得效率低下。而 ChatBI 的出现,正以自然语言交互为核心,为工业数据交互带来了革…

结婚证识别科技:利用OCR和深度学习实现婚姻证件信息的自动提取与结构化处理

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

BOE(京东方)荣获第四届“纪念彼得德鲁克中国管理奖” 创新管理模式获权威认可

11月11日,“2025纪念彼得德鲁克中国管理论坛”在南京顺利召开。BOE(京东方)凭借其融合战略引领、创新驱动、卓越运营与文化支撑为一体的创新管理模式,在长期产业实践中成效卓著,并从近百家参选企业中脱颖而出,荣…

云服务模式进化论:企业云战略的致命误区,从IaaS到FaaS的死亡之旅!

本文深度解析云计算五大服务模式(IaaS、PaaS、SaaS、BaaS、FaaS)的技术本质、商业价值与落地实践,指出没有最好的模式,只有最适合企业业务场景和发展阶段的选择,并分享了不同规模企业的选型策略与转型经验。关注我…

青少年电子设计比赛培训笔记3

初识图形化编程 Mixly软件使用 软件下载软件下载:https://pan.baidu.com/share/init?surl=s0Xl2JiUeMnvZsb452maqQ?pwd=nm35 需要下载并安装驱动程序和编程软件软件使用介绍 软件界面:开发板连接及程序烧录使用Typ…

#题解#洛谷P1314#二分#前缀和#

[传送门](P1314 [NOIP 2011 提高组] 聪明的质监员 - 洛谷) 分析 1.W变大,则要求条件更严格,则sigema(y)不增,具有单调性,考虑二分查找W。O(log w) 2.对于每一个W,可以处理前缀和求特征值。O(n+m) 3.总时间复杂…

Python 实现对遥感影像根据DN值上色

Python 实现对遥感影像根据DN值上色import os import re import glob import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt import rasterio from rasterio.plot import plotting_extent fr…

《团队作业2》需求规格说明书

团队作业2-《需求规格说明书》 随笔:星瀚餐递——校园轻量外卖平台作业维度 具体内容所属课程 https://edu.cnblogs.com/campus/gdgy/Class12Grade23ComputerScience作业要求 https://edu.cnblogs.com/campus/gdgy/Cl…

【免费】MySQL自动化运维工具,一键生成WORD和EXCEL

【免费】MySQL自动化运维工具,一键生成WORD和EXCEL

实用指南:轻量化 + 绿色部署的日志监控系统log-monitor设计思路(一)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

深入理解C++智能指针:掌握RAII与内存安全的利器 - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …