MSI参考计数:两个产品安装相同的MSI

10

当产品A和B都安装了多个MSI且其中一些MSI是相同的,卸载A或B会影响另一个吗? 安装位置是否重要?

另外,当共享的MSI C在Product B中的版本较高并且B在安装时升级了C时会发生什么? 现在卸载B将删除共享的MSI C,从而破坏Product A。如何优雅地处理此问题而不使用Permanent标志?


“Product” 是什么意思?是指 WiX 引导程序(也称为 burn)安装程序吗? - Tom Blodget
简单来说,就是将一起变化的文件捆绑在一起。如果依赖关系和重叠太多,您需要更好地分解整体部署结构。共享文件一起变化,产品发布文件一起变化 - 但有一些可管理的例外情况。 - Stein Åsmul
3个回答

15
这个问题让人首先想到的是,所涉及的产品是否按照应有的方式进行了分解。
通常情况下,所有的MSI文件都认为自己拥有安装的一切内容,并且如果组件GUID内部的引用计数为零,则在卸载时会卸载与之关联的所有内容。
但是,这个规则有一些限制:
- 如果组件被标记为“永久”,则永远不会被卸载。 - 如果文件/注册表项根本没有组件GUID,则它将被安装,而Windows Installer也不会跟踪它,因此它也不会被卸载。 - 最后,MSI的引用计数允许同一个组件在多个产品之间共享,在卸载期间,如果该组件被多个其他安装程序包注册使用,则它将在磁盘上保留。
创建MSI包之间共享组件的机制通常有以下几种: Merge模块可让您安装共享组件,这些组件是基于引用计数的,并且如果系统上存在其他客户端使用GUID,则在卸载相关产品后将保留在磁盘上。Merge模块在编译时合并到其他MSI包中。如果您喜欢的话,它是一种二进制早期绑定形式。它可以合并到任何包中。
随着Wix(基于xml的安装程序源文件)的出现,可以通过XML源包含文件而不是合并模块从几个设置中包括相同的文件段。在我看来,这要好得多,因为Wix对于源代码控制工作得更好(请参阅Wix链接以获取解释)。重要的是要意识到,“Wix源包含文件”与合并模块具有完全相同的效果-其组件被正确地引用计数,以便在不同的安装程序包之间共享,前提是源文件中的GUID已硬编码(我建议不要为此特定目的使用自动生成的GUID)。我个人认为,您应该为通用运行时文件使用第三方合并模块,但仅使用Wix包含您自己的共享文件。在我看来,Merge模块比Wix包含更难管理。

更新和文件替换:

  • 在更新场景中,MSI文件替换规则将负责更新较新的文件,取决于特殊的Windows Installer属性REINSTALLMODE的整体设置。
  • 通常情况下,较高版本的文件会覆盖较低版本的文件。如果未经修改,则非版本化文件将被覆盖。如果它们被修改,则创建和修改日期时间戳不同,文件将保持原样。
  • 请记住,降级文件问题在整个MSI设计中是被积极反对的。如果您需要降级文件(共享或非共享),则您的设计存在一些部署问题

此时,我建议您仔细阅读这些答案:

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

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

为了稳定性,非常重要的是在被太多安装程序使用之前,共享组件必须稳定,因为通常修复错误需要重新编译所有合并到共享组件中的安装程序。简单来说:将一起更改的文件捆绑在一起

为了解决大量重新编译的需求,您可以选择提供一个独立的支持设置,其中包含一些共享组件。一个或几个这样的"共享组件设置"可能包含一起进行类似的Wix包含的慢速发布计划,然后每个产品单独设置应该能够满足任何部署需求,同时保持可维护性和灵活性之间的平衡。
产品设置应该经常重新编译,共享模块设置应该设计为最小化重新编译。然后等待不断变化的需求 :-).
对我来说,这一切都关乎内聚耦合,以及在销售、市场营销和技术需求之间取得平衡的难度。

我大部分时间都在尝试通过XML源包含文件来使其工作。我已经在一个设置库中的包含文件中定义了我的AppPool,并且具有预定义的GUID ID。它被两个安装项目所引用,这些项目创建简单的网站。它安装了网站并共享了AppPool,但是当我卸载它们中的任何一个时,AppPool会被删除,而另一个网站会出现故障。我做错了什么?你能提供一个基本示例吗? - Russell Horwood
你需要硬编码GUID,以便在版本之间保持稳定,并允许引用计数按设计工作。请检查您是否自动生成了相关组件的GUID。 - Stein Åsmul
当我说“设置库中预定义的GUID ID”时,我的意思是我已经在共享组件中硬编码了GUID。我还添加了值为“yes”的“Shared”属性。但仍然出现相同的行为。 - Russell Horwood
最终在我从共享组件中移除了keypath属性并将Directory="TARGETDIR"替换后,它终于可以工作了。 - Russell Horwood

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

1
即使我正在寻找上述问题的答案,但在Wix v3.7及更高版本中,MSI包会自动被Burn引擎进行引用计数。我已经测试过了,它运行得非常完美。 同样的内容可以在Rob's blog中进行检查。

考虑到提问和回答之间的时差,您可以考虑将其作为对已接受答案的评论留下。 - PavoDive

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接