我使用WIX创建安装标准文件的MSI(没有exe, com, DLL等)。在某些用户计算机上,MSI中的某些文件可能已经存在。在安装过程中,这不是问题,因为MSI会自动更新较旧的文件等。但是,在卸载过程中,我遇到了我的问题。
用一个例子来解释是最容易的:
乔·布洛格斯的电脑上有"文件B"。这个文件没有被MSI软件包安装,也没有被微软安装程序系统跟踪。它只是电脑上的一个普通文件。
Joe Bloggs下载并安装了我的包,其中包含"文件A","文件B"one_answers"文件C"。当他安装我的包时,微软安装系统检查"文件B"并确定它与我包中的"文件B"相同。因此,它不会替换"文件B",但它确实标记了文件B是已安装的MSI组件的一部分。
Joe Bloggs决定他不喜欢我的软件,所以卸载了我的软件包。当他这样做时,所有3个文件都被删除,尽管"文件B"在我的软件包安装之前已经存在。我的调查已经确定,这是因为包含"文件B"的组件被标记为已安装。因此,当您卸载包时,它会删除"文件B"。
这有点技术性,但希望有一个WIX/MSi专家知道一个解决方案。
感谢Jim
如果这些文件可能已经存在于机器上,则标记为Component/@SharedDllRefCount="yes"
Windows安装程序将自动更新引用计数,如果它发现文件已经存在。
这通常通过备份和恢复自定义操作来完成。
基本上,您编写一个自定义操作,它可以根据接收到的参数复制一些文件。然后,您可以在安装程序中使用此自定义操作两次:
- 在安装过程中将原始文件复制到备份文件夹中(通常是临时文件或应用程序数据)
- 在卸载期间将备份文件复制回原始位置
这是使用MSI时已知的"问题",通常是由错误的部署策略引起的。缺少引用计数实际上仅仅是一种容易出错的部署方法的症状。
在任何情况下,您的安装程序都不应该干扰在运行安装之前存在或可能存在的文件。这包括您自己安装的文件,这些文件是由您自己的另一个安装程序引用计数的!想想凝聚力&;
这条通用规则通常会引发"我们的情况很特殊"之类的回应。相信我,不是的。应用程序应该在"程序文件"下使用自己的安装文件夹,在"用户设置"下使用自己的文件夹,在"共享设置"中使用自己的文件夹。不应该替换或更新共享文件,如用户字典、排除列表或类似的文件。
通常,这样的方法是为了方便"开发人员",其中配置文件需要默认值才能使应用程序运行。完全不能接受的。应用程序本身可以访问共享文件,甚至可以在有访问权限的情况下更新它们,但是它可以而不是用"默认设置"替换整个文件,或者在卸载时卸载整个文件。在没有基本配置文件的情况下创建运行环境是应用程序的责任。这些文件应该从应用程序的内部默认值中生成,或者从其他地方的只读默认文件中复制。
如果你在不同的安装程序之间共享配置文件,我会用合并模块部署它们,或者简单地将包含文件的组件设置为"shared"one_answers"permanent"one_answers"never replace If already exists"。这样做应该是对您所描述的症状的"简单修复",即使您没有遵循我上面推荐的部署建议。我知道的唯一方法就是黑入注册表。如果你增加
HKLMSOFTWAREMicrosoftWindowsCurrentVersionSharedDLLS<your dll name>
值在MSI完成创建后,在卸载过程中,MSI将看到该文件仍在使用中,而不是删除它。这是相当粗糙的,但它会工作。
或者您可以将文件备份到另一个位置,然后在卸载时将它们复制回来。
让我试着补充一个比我之前写的更好的答案。看来我没有读懂问题。我将尝试将其分解为几个选项:
- 有可能使用Windows Installer安装文件,然后根本不跟踪引用计数。换句话说,它们永远不会被卸载。您可以通过将包含文件的组件GUID清空来完成此操作。
- 然而,在我看来,像这样没有被MSI跟踪的文件是真正的数据文件,不应该以正常的方式处理。相反,您可以将它们以只读方式安装到共享位置(例如程序文件),然后您可以让应用程序将它们复制到每个用户自己的数据文件夹中。然后它们就不会被MSI引用,没有任何东西会触及它们。关于这个主题的更详细的讨论可以在这里找到:http://forum.installsite.net/index.php?showtopic=21552
- saschabeaumont的Component/@ sharedllrefcount ="yes"的方法也应该工作(我还没有测试)。这个设置的作用是在注册表中增加传统风格的sharedll refcounter (HKLMSOFTWAREMicrosoftWindowsCurrentVersion sharedll )。因此,它是一个非msi参考功能,我个人不会太依赖它。MSI引用计数以更复杂的方式在HKLMSOFTWAREMicrosoftWindowsCurrentVersionInstaller和HKCRInstaller以及其他地方完成。不要直接碰这里的任何东西!
对于MSI组件,一个好的经验法则是,一旦你为组件定义了一个关键路径(注册表或磁盘上的绝对路径),Windows安装程序认为它"拥有关键路径"并将对其进行引用计数。如果ref-count为1,它将删除密钥路径和卸载时组件中的任何其他内容。