gpt4 book ai didi

wix - 在MSI卸载过程中如何删除文件?

转载 作者:行者123 更新时间:2023-12-04 21:43:25 25 4
gpt4 key购买 nike

我想知道在卸载过程中安装的文件/组件到底发生了什么。

对于安装和升级过程,MSDN中存在可靠的文档(例如,请参见File Versioning RulesDefault File Versioning)。

无论如何,我在MSDN或WiX的文档中找不到有关卸载删除逻辑的文档。

因此,我的问题很简单:我想知道何时从系统中确切删除了一个文件(情况并非总是如此-例如,该文件是否存在/保留)。

我找到的最接近的是以下MSDN link,它提供了一些建议,但基本上说:“自己测试”。
这对我来说并不令人满意,因为在将任何使用此行为的安装程序交付给客户之前,我想知道是否可以依靠MSI的行为(也许是当前的行为)。

我正在寻找以下问题的可靠答案:


在哪种情况下-除了明确的“永久”定义或使用SharedDLLRefCount-文件/组件能否在卸载操作中幸免?
如果DLL的版本现在比安装时的版本高(由于热修补等),是否可以安全地删除它?注意:我已经对此进行了测试,当前答案是“是”,但是我需要知道这是否是预期的行为以及是否可以依靠它。

最佳答案

MSI文件的组件引用是在Windows Installer组件的基础上完成的,而不是基于在注册表中找到的旧的SharedDLL引用计数:HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLs
SharedDLL:奇怪的是,有时SharedDLL引用计数器也与MSI一起使用,但这只是为了与旧版安装程序和部署技术兼容-我将在以后说明。传统技术使用此SharedDLL计数器作为确定是否可以卸载文件的唯一方法。只要ref-count降为0,就可以删除该文件。
Windows Installer的实际引用计数是基于Windows安装程序组件而不是共享的dll引用计数器完成的。这些组件是文件和注册表设置的“基本安装包”。它始终作为一个整体安装或卸载。组件基本上可以包含“任何内容”,但是在分解要部署到组件集合中的文件和注册表设置时,存在关于最佳实践的规则。我个人总是为每个组件使用一个文件,因为这样可以避免Windows Installer升级期间出现的各种问题。
密钥路径:本质上,每个组件都有一个“密钥路径”-单个文件或注册表项/值,用于确定组件是否已安装。 MSI的总体概念是,在此绝对组件密钥路径和唯一组件GUID之间存在一个1-to-1 mapping。 GUID本质上引用计数该绝对路径。几年前,我在一个答案中对此进行了解释,这似乎是对人们的一种容易理解的解释,也许可以快速阅读一下以更详细地了解此组件引用:Change my component GUID in wix?
合并模块:此组件GUID(用于特定的绝对磁盘或注册表位置)应由所有试图部署有问题的文件或组件的安装程序使用。允许安装的Window Installer机制称为“合并模块”。这是一个部分MSI数据库,可以在构建时合并到几个MSI文件中-允许在MSI文件之间共享相同的组件,并在所有文件中使用正确的组件GUID,从而可以进行引用计数。这允许这些共享组件在每次由不同产品安装时都会增加引用计数,然后该组件将保留在系统上,直到将使用它的产品按顺序卸载的引用计数减少到0为止。应该注意的是,如果HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLs上的旧版引用计数器同时不是0,则不会卸载该组件。如果将组件设置为永久性,或者使用空白组件GUID安装了该组件,则该组件也不会被卸载(“安装并忘记”一个组件的特殊功能-不再对其进行处理)。
GUID:因此,再重复一遍,一个GUID代表一条绝对路径(一个GUID统治所有规则)-一个GUID具有关联的引用计数器,该计数器计算已注册组件的产品数量及其关联的绝对键路径。 ,以供使用。因此,作为示例,三个产品可能会注册某个组件GUID的使用,使其引用计数为3,并因此使其相关的密钥路径文件或注册表值始终存在,直到卸载所有这三个产品为止。
SharedDLL是否已启用?:请注意,不一定为您的MSI组件启用了旧版SharedDLL引用计数器。某些工具(例如Installshield)启用标志来增加所有已安装文件的旧版共享DLL引用计数器,实际上,您必须为每个组件都将其关闭以摆脱此现象。这与其他工具(例如WiX)形成对比,后者未将所有文件的共享dll引用计数器默认设置为打开(我不确定它们启用了哪些文件-如果有的话)。 Advanced Installer也不为所有组件启用SharedDLL ref-count标志(感谢Bogdan Mitrache进行了验证-请参阅下面的评论)。


混乱的旧式参考计数器-在开发和测试安装过程中可能会发生-可能会导致Windows Installer
应该卸载的组件会意外地留在磁盘上。
如果看到此错误,请检查系统是否干净,确定是否混乱
老式引用计数器是您主机上的问题。然后,您需要
手动调整注册表以修复您的引用计数
开发机器。这将涉及本项下的所有适用项目
键:HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLs
这不是一项有趣的工作-使用Installshield Developer 7时发生了这种情况
追溯到一天。
未能为每个绝对键路径都保持一致的组件GUID会导致神秘且无法预测的问题,例如MSI
卸载以删除仍与其他产品共享的文件,
但是引用计数已被弄乱了。 MSI文件
错误地认为他们“拥有”共享组件并愉快地删除
他们。身份错误的情况(同一绝对路径有多个
指向它的组件GUID-每个引用都计为1)。
这是人们使用Windows Installer面临的关键问题之一-
因此建议每个组件坚持一个文件。


更新:让我们具体说明您的特定问题。

您已经差不多回答了这个问题。如果您的MSI文件在卸载时递减了其“注册”之后,如果组件的引用计数(对于组件GUID)大于0,则文件将保留在磁盘上。如果它的MSI组件设置为永久组件,或者具有空白组件GUID,或者为该组件启用了旧版SharedDLL引用计数(可能不是),并且此处的引用计数更高,则该字段也将保留。大于0:HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLs。这些都是我所知道的条件。我想还有其他方面,例如广告产品,但是老实说,我不确定它们将如何影响卸载。广告产品不是真正安装的,而是由用户根据需要“安装”的。阅读Phil的答案,我还记得,transitive components也可以按照他在答案中描述的方式进行卸载-通过在重新安装期间将相关条件评估为false。

是的,只要在特定的绝对路径(文件的完整安装路径)的整个生命周期中组件GUID保持稳定,则该文件可以进行任意数量的更新,并且引用计数仅在存在其他更新时才递增带有其他产品代码的MSI也会安装它。换句话说:如果您已对原始MSI进行了4次更新,并且为特定文件维护了一致的组件GUID,并且每次使用新版本进行更新,则该文件的组件引用计数仍为1-只要没有其他MSI也没有安装该组件-在这种情况下,它将是2个或更多,并且卸载您的产品不会将其卸载,但是会将引用计数减少1。


请尝试阅读此答案,因为它似乎已经为其他人澄清了一些问题:Change my component GUID in wix?(与上面的建议相同)。

最后,我应该指出,共享组件也可以通过WiX包含文件安装-WiX完全引入的新概念。这些就像C ++中的常规包含文件一样,只需定义一次即可,并且可以在编译时将它们包含在多个WiX源文件中。老实说,我从来没有使用过它,但是从概念上讲,它类似于合并模块-内置Windows Installer概念来处理共享组件。但是,有一个重要的区别:合并模块是整体版本化的,而WiX包含文件则包含源文件夹中的动态文件。我觉得更好,但这当然是一个很大的讨论,而且是一个偏爱的问题。我将不在这里详细说明。
如果您使用的是WiX,建议您尝试使用WiX包含文件来管理共享组件。在我看来,它们似乎是合并模块的更灵活的实现。从主观上讲,我从来都不是合并模块的忠实拥护者,尽管如果您有很多要与其他产品一起安装的共享文件,则必须使用合并模块。为什么我不喜欢合并模块?它们看起来像是一个额外的复杂问题,并且需要额外的维护。实际上,它们相当于一种奇怪的静态链接形式-带有我们从常规静态链接中了解到的所有问题。这可能太主观了,所以我将在此结束说明,但是对于共享文件和组件,请使用合并模块或WiX包含文件或存在的任何其他构造来实现我所不知道的相同目的。

关于wix - 在MSI卸载过程中如何删除文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48116792/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com