WIX / MSI - 卸载时是否可以创建一个包装,该包保留安装前存在的文件

时间:2011-04-20 12:18:06

标签: wix installer windows-installer uninstall

我正在使用WIX创建安装标准文件的MSI(没有exe,com,DLL等)。在某些用户计算机上,MSI中的某些文件可能已经存在。在安装过程中这不是问题,因为MSI会自动更新较旧的文件等。但是,在卸载过程中我遇到了问题。

最简单的解释一个例子:
Joe Bloggs在他们的计算机上有“文件B”。此文件尚未由MSI程序包安装,并且无论如何都不会被Microsoft Installer系统跟踪。它只是计算机上的普通文件。

Joe Bloggs下载并安装我的包,其中包含“文件A”,“文件B”和“文件C”。当他安装我的软件包时,Microsoft Installer系统会检查“文件B”并确定它与我的软件包中的“文件B”相同。因此它不会替换“文件B”,但它会标记文件B是安装的一部分的MSI组件。

Joe Bloggs然后决定他不喜欢我的软件,所以卸载我的软件包。当他这样做时,尽管在我的软件包安装之前存在“文件B”,但所有3个文件都被删除。我的调查已经确定这是因为包含“文件B”的组件被标记为已安装。因此,当您卸载软件包时,它会删除“文件B”。

这有点技术性,但希望有一位知道解决方案的WIX / MSi专家。

由于

吉姆

5 个答案:

答案 0 :(得分:3)

如果文件可能已存在于机器标记Component/@SharedDllRefCount="yes"

如果Windows安装程序发现已存在的文件,则会自动更新引用计数。

答案 1 :(得分:2)

这通常通过备份和还原自定义操作来完成。

基本上,您编写了一个自定义操作,可以根据收到的参数复制某些文件。然后,您可以在安装程序中使用此自定义操作两次:

  • 在安装期间将原始文件复制到备份文件夹(通常是临时或应用程序数据)
  • 在卸载期间将备份文件复制回原始位置

答案 2 :(得分:2)

使用MSI时这是一个已知的“问题”,通常是由错误的部署策略引起的。缺少引用计数实际上仅仅是容易出错的部署方法的症状。

在安装运行之前,安装程序几乎不会干扰存在或可能存在的文件。这包括您自己安装的文件,这些文件是由您自己的另一个安装程序计算的!想想凝聚力和耦合,只有一个安装程序应该处理每个文件。

这个一般规则通常会触发“我们的案例很特殊”的回应。相信我,事实并非如此。应用程序应在Program Files下使用自己的安装文件夹,在用户设置下使用自己的文件夹,在共享设置中使用自己的文件夹。它应该从不替换或更新共享文件,例如用户词典,排除列表或类似文件。

这种方法通常是为了促进“开发人员注册”,其中配置文件需要应用程序的默认值才能运行。完全不能接受。应用程序本身可以访问共享文件,如果它有访问权限,甚至可以更新它们,但它可以用“默认设置”替换整个文件,或者在卸载时卸载整个文件。 在没有基本配置文件的情况下创建运行环境是一项应用程序职责。这些文件应该从应用程序内部默认值生成,或者从放置在别处的只读默认文件中复制。

如果您在不同的安装程序之间共享配置文件,我会使用合并模块部署它们,或者只是将包含文件的组件设置为“共享”并且“永久”和“永不替换,如果已存在”。这样做应该是您所描述的症状的“简单修复”,即使您不遵循我上面推荐的部署建议。

答案 3 :(得分:0)

我知道的唯一方法就是破解注册表。如果你增加

MSI完成创建后的

HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLS\<your dll name>值,在卸载过程中,MSI会看到该文件仍在使用中,而不是将其删除。这非常hacky,但它会起作用。

或者您可以将文件备份到其他位置,卸载后将其复制回来。

答案 4 :(得分:0)

让我尝试添加一个比我之前写的更好的答案。我似乎没有正确地阅读这个问题。我将尝试将其分解为几个选项:

  1. 可以安装带有Windows Installer的文件,这些文件根本不会被引用计数跟踪。换句话说,它们永远不会被卸载。您可以通过消隐包含文件的组件GUID来执行此操作。
  2. 但是,在我看来,MSI未跟踪的文件实际上是数据文件,不应该以正常方式处理。相反,您可以将它们只读安装到共享位置 - 例如Program Files - 然后您可以让应用程序将它们复制到每个用户自己的数据文件夹中。然后它们被MSI没有引用,没有任何东西可以触及它们。可以在此处找到有关此主题的更长时间的讨论:http://forum.installsite.net/index.php?showtopic=21552
  3. saschabeaumont 的组件/ @ SharedDllRefCount =&#34;是&#34;方法也应该有效(我没有经过测试)。此设置的作用是在注册表中增加旧式样式SharedDll引用计数器( HKLM \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ SharedDLLs )。因此,这是一个非MSI参考功能,我不会过分依赖它。 MSI引用计数在 HKLM \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Installer HKCR \ Installer 等其他地方以更复杂的方式完成。 不要直接碰到任何东西!
  4. 带有MSI组件的良好的经验法则是,一旦您为组件定义了一个密钥路径(注册表或磁盘上的绝对路径),Windows Installer就会认为它是&#34;拥有关键路径&#34;并将参考计算它。如果ref-count为1,则删除密钥路径以及卸载时组件中的任何其他内容。