- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想知道在卸载过程中安装的文件/组件到底发生了什么。
对于安装和升级过程,MSDN中存在可靠的文档(例如,请参见File Versioning Rules和Default 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/
我一直在尝试查找文章或发布列出 WiX (Windows Installer XML)/WiX 工具集的功能限制的文章,但均未成功。使用 WiX 几个星期后,我至少能想到两个 限制 在最新的 RTM
我们在 SomeDialog.wxs 文件中有一个 WiX 片段,它会提示用户输入一些信息。它在 InstallerUI.wxs 文件中控制对话框顺序的另一个片段中被引用。当然,Product.wxs
我们有多个配置文件。根据所选的环境,正确的文件将被复制,其余文件应被删除。 我正在使用RemoveFile,但是不会删除任何内容,或者可能是我没有正确使用它。复制所有文件后,有人可以举一个例子在安装过
我正在为现有产品编写 MSI。在以前的版本中有一个自定义操作,它不仅限于在安装时运行,现在在使用 MajorUpgrade 卸载时失败。 新安装程序中是否有任何方法可以告诉 WiX 在卸载时跳过该特定
我需要在安装之前检查 .NET Framework。我添加了这个 文件的开头包含 并在链接时出现错误 error LGHT0094 :
如果在功能选择树中选择了另一个功能,是否有任何方法可以强制安装特定功能?那就是没有让功能成为它们依赖项的子项? 最佳答案 是的,这应该是可能的,如果您在 Feature 元素下使用 Condition
有没有办法在 WiX 中强制自动登录? 目前,要生成日志,我需要使用此参数执行我的包: application.msi /l*v log.txt 我想在 中找到一个方法标记 - 例如 - 强制日志始
我正在为我的项目创建一个 WIX 模板,以确保相对标准的布局。 我已经使用 定义了一个变量来引用主应用程序其中 MyApp 是引用项目的名称。然后,我使用 MainApp 变量在 .wxs 和 .w
我有一个名为 MyProject(P2P) 的 visual studio 项目,它一直运行良好。 现在我正在使用 Wix 3 将这个项目打包到 MSI 中,其中一个步骤是编写组件节点:
我正在使用Wix 3.6。我有一个问题,在卸载时是否打开了任何窗口并显示在任务栏中(此窗口是我试图卸载的msi的一部分),它显示了一个对话框,要求用户关闭应用程序(“在继续安装之前,应关闭以下应用程序
我需要澄清 *.wxs 文件中的目录结构。据我所知,它将文件安装在我们在目录元素中指定的目录中。它还有其他用途吗? 如果它确实描述了将安装产品的目录结构,那么如果用户在安装程序中有浏览选项会发生什么。
我们已经为我们的应用程序创建了 WIX 安装程序。我们面临的问题是: 我们已经定义了两个不同的自定义操作(比如 ActionForInstall 和 ActionForUninstall),我们希望在
我有一个应用程序安装程序,无论版本号如何,都需要通过任何现有版本进行安装。 相反,我有一个安装程序,不断说我需要添加/删除程序。对于我的测试人员而言,这是非常令人沮丧的行为,因为这只会在没有真正原因的
我正在使用VS 2010创建一个由Wix安装的程序,并且已经准备好product.wxs。 在我的wxs文件中,我有类似以下的目录定义:
关注 example here ,我在 ProgramMenuFolder 中添加了一个快捷方式启动我的应用程序。 (我的代码实际上更简单,因为我不需要额外的文件夹。)
即使在重新启动后,服务仍然存在,即使可执行文件消失了。我正在使用 WIX 版本 3.0.5419.0 安装 Windows 服务工作正常。卸载它似乎什么也没做。卸载日志文件的部分
我正在尝试配置 WiX 设置和库,以便将库中文件之一的版本用作设置中的 Product/@Version。 背景 在本地定义文件的设置中,这相对简单,因为假设组件项目被 WiX 项目引用然后配置:
我想在wix项目生成的msi文件的文件名中包含一些动态部分。这个动态部分应该由变量控制,这些变量是我的wix项目的一部分,并且应这样声明: 有谁知道将wix变量的值发送给链接器以将其用作输出文件名的
我真的觉得我不必为了获得这样的基本信息而在SO上提问,但是我在任何地方都找不到可靠的消息来源。 WiX v4是否已发布?开发中?在Beta中?还在设计中? 如此看来,许多人似乎已经在使用WiX v4。
如果注册表项 HKEY_CURRENT_USER\Control Panel\International\LocaleName 的值为 de-DE,我希望将 INSTALL_DE 属性值设置为 1。
我是一名优秀的程序员,十分优秀!