【问题标题】:MSI Reference Counting: Two products install the same MSIsMSI 引用计数:两个产品安装相同的 MSI
【发布时间】:2014-07-18 22:58:06
【问题描述】:

当产品 A 和 B 各自安装多个 MSI 并且某些 MSI 相同时,卸载 A 或 B 会影响另一个吗?安装位置重要吗?

另外,如果常见的 MSI C 的版本在产品 B 中较高并且 B 在安装时升级 C 会发生什么?现在卸载 B 将删除破坏产品 A 的常见 MSI C。如何在不使用永久标志的情况下优雅地处理这个问题?

【问题讨论】:

  • “产品”是什么意思?一个 WiX Bootstrapper(又名刻录)安装程序?
  • 简单的说法:将一起更改的文件捆绑在一起。如果有太多的依赖和重叠,您需要更好地分解整个部署结构。共享文件一起更改,产品发布文件一起更改 - 有一些可管理的例外情况。

标签: wix installation windows-installer wix3 merge-module


【解决方案1】:

想到这个问题的第一件事是,有问题的产品是否按应有的方式分解。

作为一般规则,所有 MSI 文件都认为他们拥有所安装的任何内容,并且如果引用计数(使用该组件的产品数量) 为零。

这条规则有一些限制

  • 如果组件标记为永久,则永远不会卸载
  • 如果文件/注册表项根本没有组件 GUID,则会安装它,Windows Installer 永远不会跟踪它,也不会被卸载
  • 最后,MSI 的引用计数 允许在多个产品之间共享相同的组件,并且如果它已被多个其他安装程序包注册使用,则它会在卸载期间保留在磁盘上

在 MSI 包之间创建共享组件的机制通常是:

  1. 合并模块允许您安装引用计数的共享组件,如果系统上有其他客户端使用 GUID,这些组件将在卸载相关产品后保留在磁盘上。合并模块在编译时合并到其他 MSI 包中。一种二进制早期绑定(如果您愿意)。它可以合并到任何包中。
  2. 随着Wix(基于xml的安装程序源文件)的出现,可以通过XML source include file而不是合并模块包含来自多个设置的相同文件段。在我看来,这是非常优越的,因为 Wix 更适合源代码控制 (see Wix link for explanation)。 至关重要要认识到“Wix 源包含文件”与合并模块具有完全相同的效果 - 它的组件被正确地引用计数以在不同的安装程序包之间共享,前提是源文件中的 GUID 是硬编码的(我建议不要将自动生成的 guid 用于此特定目的)。我个人认为,您应该将第三方合并模块用于通用运行时文件,但Wix 包含用于您自己的共享文件。合并模块比 Wix 包含 imho 更难管理。

更新和文件替换

  • 对于更新方案,MSI file replacement rules 将负责更新较新的文件,具体取决于特殊 Windows Installer 属性 REINSTALLMODE 中的整体设置。
  • 通常,较高版本的文件会覆盖较低版本的文件。未修改的非版本文件将被覆盖。如果它们被修改,则创建和修改的日期戳不同,文件将保持不变。
  • 请记住,整体 MSI 设计不鼓励降级文件的问题。如果您需要降级文件(共享或不共享),您的设计存在部署异味

此时我会彻底阅读这些答案:

如果您使用 Wix,或者您愿意使用 Wix,我认为处理重叠产品的最佳方法是将您的安装程序分解为 Wix 段源文件,然后将其包含为在您的主要安装程序中需要。这将允许卸载一个产品以保留其他应用程序使用的任何组件。

话虽如此,我不喜欢在我的安装程序中造成太多重叠的依赖项,原因在本文中列出(也在上面列出):Wix to Install multiple Applications

对于稳定性共享组件在被太多设置使用之前稳定作为一般规则作为错误修复至关重要将需要重新编译共享组件被编译或合并到的所有设置。 简单的说法:将一起更改的文件捆绑在一起

为了抵消这种对大量重新编译的需求,您可以选择提供由一些共享组件组成的独立支持设置。一个或几个可能包含 Wix 的此类“共享组件设置”包括在类似的缓慢发布时间表上一起更改,然后分开每个产品的设置应该能够满足任何部署需求,同时保持可维护性和灵活性之间的平衡

产品设置应该是经常重新编译的产品设置,并且共享模块设置应该设计为最小化重新编译。然后等待变化的需求:-)。

对我来说,这完全是关于凝聚力耦合,以及平衡销售、营销和技术需求的困难。

【讨论】:

  • 我大部分时间都在尝试通过 XML 源包含文件使其工作。我在一个包含文件中定义了我的 AppPool,该文件在设置库中具有预定义的 GUID id。它被两个创建简单网站的设置项目引用。它安装站点并共享 AppPool,但是当我卸载其中任何一个时,AppPool 被删除并且另一个网站被破坏。我究竟做错了什么?你能提供一个基本的例子吗?
  • 您需要对 guid 进行硬编码,以使其在版本之间保持稳定,并允许引用计数按设计工作。检查您是否没有为相关组件自动生成 guid。
  • 当我说“设置库中的预定义 GUID id”时,我的意思是我已经在共享组件中硬编码了 GUID。我还添加了值为“yes”的“Shared”属性。但仍然是相同的行为。
  • 在我从共享组件中删除 keypath 属性并改为 Directory="TARGETDIR" 后,终于让它工作了。
【解决方案2】:

如果产品 A 和产品 B 具有共同的 MSI C,则 如果安装了产品 A,也安装了 MSI C,现在安装产品 B 时将不会安装 MSI C,因为它已经在系统中可用(如果产品 B 基于 WiX Burn,它会注册一个依赖项)。如果产品 A 和产品 B 是基于 WiX Burn 的安装程序或任何其他支持引用计数的引导程序,则会自动处理卸载引用计数,否则 MSI C 将与产品 B 一起删除。

【讨论】:

    【解决方案3】:

    即使我一直在寻找上述问题的答案,但在 Wix v3.7 及更高版本中,MSI 包由 Burn 引擎自动引用计数。我已经对此进行了测试,并且效果很好。 同样可以在Rob's blog查看

    【讨论】:

    • 考虑到问题与您的答案之间的时间差,您可以考虑将其作为对已接受答案的评论。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-11
    • 2011-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-26
    相关资源
    最近更新 更多