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

发布于 2024-11-02 11:29:25 字数 601 浏览 2 评论 0原文

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

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

Joe Bloggs 下载并安装我的软件包,其中包含“文件 A”、“文件 B”和“文件 C”。当他安装我的软件包时,Microsoft 安装程序系统会检查“文件 B”并确定它与我的软件包中的“文件 B”相同。因此,它不会替换“文件 B”,但会将文件 B 所属的 MSI 组件标记为已安装。

然后 Joe Bloggs 认为他不喜欢我的软件,因此卸载了我的软件包。当他执行此操作时,尽管在安装我的软件包之前存在“文件 B”,但所有 3 个文件都被删除。我的调查表明,这是因为包含“文件 B”的组件被标记为已安装。因此,当您卸载该软件包时,它会删除“文件 B”。

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

谢谢吉姆

I am using WIX to create MSI's which install standard files (no exe, com's, DLL's etc). On some users computers some of the files in the MSI may already exist. During the install this is not a problem as MSI automatically updates files that are older etc. However, during uninstall I hit my problem.

It is easiest to explain with an example:
Joe Bloggs has "file B" on their computer. This file has not been installed by an MSI package and is not being track by the Microsoft Installer system in anyway. It is just a normal file on the computer.

Joe Bloggs downloads and installs my package which contains "file A", "file B" and "file C". When he installs my package the Microsoft Installer system checks "file B" and establishes it is identical to the "file B" in my package. It therefore does not replace "file B" but it does mark the MSI component that file B is part of as installed.

Joe Bloggs then decides he does not like my software so uninstalls my package. When he does this all 3 files are removed despite "file B" existing before my package was installed. My investigations have established that this is because the component that contains "file B" is marked as installed. Therefore when you uninstall the package it removes "file B".

This is all a bit technical but hopefully there is a WIX / MSi expert out there that knows a solution.

Thanks

Jim

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

亢潮 2024-11-09 11:29:25

如果文件可能已存在于计算机上,则标记 Component/@SharedDllRefCount="yes"

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

If the files may already exist on the machine mark Component/@SharedDllRefCount="yes"

Windows installer will then automatically update the reference count if it finds the files already existing.

花辞树 2024-11-09 11:29:25

这通常是通过备份和恢复自定义操作来完成的。

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

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

This is usually done through backup and restore custom actions.

Basically, you write a custom action which can copy some files based on the parameters it receives. You can then use this custom action twice in your installer:

  • once during install to copy the original file in a backup folder (usually temp or application data)
  • once during uninstall to copy the backup file back in the original location
意中人 2024-11-09 11:29:25

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

在几乎任何情况下,安装程序都不应干扰安装运行之前存在或可能存在的文件。这包括您自己安装的文件,这些文件由您自己的另一个安装程序进行引用计数!思考凝聚力和凝聚力耦合,只有一个安装程序应该处理每个文件。

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

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

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

This is a known "problem" when using MSI and is generally caused by a bad deployment strategy. The lacking reference counting is actually merely a symptom of an error-prone deployment approach.

In almost no case should your installer interfere with files that exist, or are likely to exist, before your installation is run. This includes files you have installed yourself that are reference counted by another of your own installers! Think cohesion & coupling, only one installer should deal with each file.

This general rule normally triggers a response along the lines of "our case is special". Trust me, it isn't. An application should use its own installation folder under Program Files, its own folder under user settings, and its own folder in shared settings. It should never replace or update shared files such as user dictionaries, exclusion lists or similar.

Often such an approach is to facilitate a "developer cruch" where config files need default values for the app to function. Completely unacceptable. The application itself can access shared files, even update them if it has access, but it can not replace the whole file with "default settings" or uninstall the whole file on uninstall. It is an application responsibility to create a running environment in the absence of basic configuration files. The files should then be generated from the applications internal defaults or be copied from read-only default files placed elsewhere.

If you share config files between different installers I would deploy them with a merge module, or simply set the component(s) that contain(s) the file(s) to "shared" and "permanent" and "never replace if already exists". Doing so should be the "easy fix" to the symptom you describe, even if you don't follow the deployment advice I recommend above.

擦肩而过的背影 2024-11-09 11:29:25

我知道的唯一方法就是破解注册表。如果在 MSI 完成创建后增加

HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLS\ 值,则在卸载过程中 MSI 将看到该文件仍在使用中,并且不删除它。这很hacky,但它会起作用。

或者您可以将文件备份到另一个位置,然后在卸载时将它们复制回来。

The only way I know would be to hack the registry. If you increment the

HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLS\<your dll name> value after MSI has finished creating it, during uninstall MSI will see that the file is still in use and not remove it. This is pretty hacky, but it would work.

Or you could back the files up to another location, and on uninstall, copy them back.

疏忽 2024-11-09 11:29:25

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

  1. 可以使用 Windows Installer 安装文件,然后根本不会通过引用计数来跟踪这些文件。换句话说,它们永远不会被卸载。您可以通过删除包含该文件的组件 GUID 来完成此操作。
  2. 然而,在我看来,像这样未被 MSI 跟踪的文件实际上是数据文件,不应该以正常方式处理。相反,您可以将它们以只读方式安装到共享位置(例如 Program Files),然后您可以让应用程序将它们复制到每个用户自己的数据文件夹中。然后,MSI 将不再引用它们,并且任何内容都不会触及它们。有关此主题的详细讨论可以在这里找到:http://forum.installsite.net/ index.php?showtopic=21552
  3. saschabeaumont 的 Component/@SharedDllRefCount="yes" 方法也应该有效(我尚未测试)。此设置的作用是增加注册表中旧式 SharedDll 引用计数器 (HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLs)。因此,它是一个非 MSI 参考功能,我个人不会太依赖它。 MSI 引用计数在 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\InstallerHKCR\Installer 等地方以更加复杂的方式完成。 不要直接触摸此处的任何内容!

对于 MSI 组件,一个好的经验法则是,一旦定义了关键路径(注册表中或磁盘上的绝对路径)对于一个组件,Windows Installer 认为它“拥有关键路径”并对其进行引用计数。如果引用计数为 1,它将删除关键路径以及卸载时组件中的任何其他内容。

Let me try to add a better answer than the one I wrote before. It seems I may not have read the question properly. I will try to break this down to a few options:

  1. It is possible to install files with Windows Installer that are then not tracked by reference counting at all. In other words they are never uninstalled. You do this by blanking out the component GUID containing the file.
  2. However, in my opinion files that are not tracked by MSI like this are really data files, and should not be dealt with in the normal way. Rather you can install them read-only to a shared location - for example Program Files - and then you can have your application copy them to each user's own data folder. They are then unreferenced by MSI and nothing will ever touch them. A longer discussion of this topic can be found here: http://forum.installsite.net/index.php?showtopic=21552
  3. saschabeaumont's Component/@SharedDllRefCount="yes" approach should also work (I haven't tested). What this setting does is to increment the legacy style SharedDll ref-counter in the registry (HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLs). As such it is a non-MSI reference feature and I wouldn't rely too much on it personally. MSI reference counting is done in a much more intricate way in HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer and HKCR\Installer among other places. Don't touch anything here directly!

A good rule of thumb with an MSI component, is that once you define a key path (absolute path in the registry or on disk) for a component, Windows Installer thinks it "owns the key path" and will reference count it. If the ref-count is 1 it deletes the key path and anything else that was in the component on uninstall.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文