wix - 如何避免使用 Windows Installer / MSI 安装产品的两个版本?
问题描述
我已经编写并维护了许多 Wix 安装源文件,这些文件用于构建 MSI 文件以分发我的应用程序。
我没有为任何类型的升级、更新、重新安装或任何类似的东西明确编程——有一个功能由许多具有稳定 GUID 的组件组成,我观察到至少干净的安装可以满足我的期望它到。
但是,我(以及拥有我分发的 MSI 文件的任何人)可能会使用它们各自的(不同的)MSI 文件并排安装我的应用程序的不同版本。这本身不是问题,除了我显然使用与安装目标相同的文件夹 - “%ProgramFiles(x86)%\Foobar” - 来安装应用程序(无论版本)。这意味着实际上有总是有一个版本最终被安装。
我认为到目前为止,Windows Installer 的行为是正确的,它会从它最后安装的任何 MSI 包中更新文件。这样做的一个有趣的副作用是,如果最后一个 MSI 是早期版本,则应用程序文件夹中的文件将被该早期版本的副本覆盖。
但这对我来说似乎都不是真正的问题。我想解决实际安装的内容(单个应用程序版本)和 Windows 跟踪安装的内容之间的差异——在我的例子中,两个不同的应用程序版本的两个记录。
由于我将应用程序安装在不依赖于所安装版本的文件夹中,因此通过 Windows 跟踪多个应用程序版本是错误的。
所以我想我的问题是,我该如何解决这个问题,以便只显示一个版本(反映现实)或者在这种情况下的惯用方法是什么?我故意没有过度指定我的 Wix 源代码,希望作为回报,Windows Installer 会使用一些内置的智能来自行解决所有问题。但我想我可能需要添加一些明确的升级或卸载先前版本的说明。
我缩小的 Wix 源代码(文件“foobar.wxs”)如下所示:
<?xml version="1.0" encoding="utf-8" ?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Product Name="Foobar" Manufacturer="ACME Inc." Id="*" UpgradeCode="ae9a7d6d-6c2d-446a-97d9-9dbe829d2ea8" Language="1033" Codepage="1252" Version="!(wix.PRODUCT_VERSION)">
<Package Id="*" Languages="1033" SummaryCodepage="1252" Compressed="yes" InstallerVersion="200" />
<Icon Id="foobar" SourceFile="!(wix.APPPATH)/foobar.ico" />
<Property Id="ARPPRODUCTICON" Value="foobar" />
<Property Id="ARPCOMMENTS" Value="Gives you full foobar powers" />
<MediaTemplate EmbedCab="yes" CompressionLevel="high" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="DesktopFolder" />
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLDIR" Name="Foobar" FileSource="!(wix.APPPATH)">
<Component>
<File Id="foobar.exe" Name="foobar.exe" />
</Component>
<!-- There are other components like above (assets) -->
</Directory>
</Directory>
<Directory Id="ProgramMenuFolder">
<Directory Id="foobar_menu" Name="Foobar">
<Component Id="foobar_shortcut" Guid="e80a6b95-a145-453a-b327-65a977e741fe">
<Shortcut Icon="foobar" Id="foobar_shortcut" Name="Foobar" Target="[foobar]foobar.exe" />
<Shortcut Directory="DesktopFolder" Icon="foobar" Id="foobar_desktop_shortcut" Name="Foobar" Target="[foobar]foobar.exe" />
<RegistryValue KeyPath="yes" Root="HKMU" Key="Software\[Manufacturer]\[ProductName]" Type="string" Value="" />
<RemoveFolder Id="remove_foobar_menu" On="uninstall" />
</Component>
</Directory>
</Directory>
<Directory Id="CommonAppDataFolder">
<Directory Id="app_data_foobar" Name="foobar">
<Component Guid="" Id="app_data_config_folder">
<CreateFolder />
</Component>
<Component Guid="" Id="app_data_config_folder_log_file">
<File Name="foobar.log" Source="foobar.log.template">
<!-- Add write access permission to the log file to members of "Users" group. -->
<!-- PermissionEx Sddl="D:AR(A;;GWGR;;;BU)" / -->
<!-- Bug with Windows Installer, can't use PermissionEx/MsiLockPermissionsEx table. See https://stackoverflow.com/questions/55145282/how-to-include-inherited-permissions-when-specifying-permissions-for-a-file-inst -->
<util:PermissionEx Append="yes" GenericWrite="yes" User="Users" />
</File>
</Component>
</Directory>
</Directory>
</Directory>
<Feature Id="foobar">
<ComponentGroupRef Id="foobar" />
<ComponentRef Id="foobar_shortcut" />
<ComponentRef Id="app_data_config_folder" />
<ComponentRef Id="app_data_config_folder_log_file" />
</Feature>
</Product>
</Wix>
我正在使用以下 Windows 命令提示行编译目标文件:
candle.exe -ext WixUtilExtension -out %TEMP% foobar.wxs
然后使用以下命令生成 MSI 文件:
light.exe -ext WixUtilExtension -spdb "-dAPPPATH=%apppath%" "-dPRODUCT_VERSION=%version%" -out %TEMP%\foobar-%version%.msi %TEMP%\foobar.wixobj
(使用 Wix 3.11.1.2318)
解决方案
升级代码:只要您设置了升级代码(识别一堆相关产品),您就可以使用主要升级元素来指示要作为新 MSI 安装的一部分卸载的产品。
MajorUpgrade 元素:只需注入一个MajorUpgrade 元素,即可将主要升级的默认处理方式注入到您现有的 WiX 源中。它是一种“神奇元素”,可以为您做出许多(通常是好的)假设做很多事情。有更旧且更灵活的方法来做到这一点 - 如果您需要更详细的控制(通常用于遗留目的 - 自动魔术并不涵盖所有基础):
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
以上是在 Visual Studio 中创建的所有 WiX 文件的标准用法。
注意:我将尝试使用更多链接尽快调整此答案,但先试一试?
第一个链接:使用 Visual Studio 制作 WiX 文件。Hello WiX 和 Visual Studio 类型的场景。
重大升级建议阅读:关于重大升级的一些事情。所有 WiX 标记本质上都围绕已编译的 MSI升级表。在那里配置了主要的升级逻辑。自定义操作也可能会影响某些事情,可能还会影响其他一些事情,例如启动条件。
- WiX 文档:如何:在您的安装程序中实施重大升级
- 主要升级 -
Common Problems
: WIX 不卸载旧版本 - 主要升级 -
Manual Configuration
:向 MSI UpgradeTable 添加条目以删除相关产品(使用旧式升级元素)
进一步:
- 主要升级 -
How-To & Concept
:在 Wix 中进行主要升级会在添加/删除程序中创建 2 个条目
推荐阅读
- javascript - 如何用createElement渲染Vue的动态组件标签?
- snowflake-cloud-data-platform - 什么是磁盘溢出意味着以及如何在雪花中避免这种情况
- html - 如何删除所有默认锚样式以使元素不受影响?
- python - 冒泡排序算法和“int”对象不可下标
- r - 无法在 R 中安装 bbplot 包
- node.js - 如何将搜索结果发送回客户端?
- c - 我可以使用逻辑 OR(||) 运算符而不是逻辑 AND(&&) 运算符吗
- python - 我不明白为什么这个嵌套的while循环可以工作请python
- powershell - 无法使用字符串在 PowerShell 中设置别名
- php - MYSQL查询海量泵