如何避免使用我的 WiX / MSI 包触发 MSI 自我修复?

How do I avoid triggering MSI self-repair with my WiX / MSI package?

如何避免从我的 WiX 生成的 MSI 包中触发自我修复?


这是一个 Q/A-style 问题,其答案仅列出了一些不要在 MSI 文件中做的事情以避免最常见的问题重复自修复的原因

Self-Repair, Simple & Short Explanation: Why does the MSI installer reconfigure if I delete a file?


General WiX / MSI Advice: This self-repair piece was split from the original answer on general MSI problems:


简短摘要

我一直在尝试写关于为开发人员重复 MSI 自我修复,但最终写得太多了。这是我的最后一次尝试:具体设计建议 不该做的事情 在您的 WiX / MSI 文件中 .其他部署专家,请扩展下面的“陷阱列表”。


我写的 早期答案 原来是与开发人员相关的,但对开发人员不友好:

  • How can I determine what causes repeated Windows Installer self-repair? - 侧重于理解一般的自我修复问题。设置开发人员/应用程序打包程序焦点。
  • - 提供 清单 用于解决自我修复方案。 “如何固定焦点” - 而不仅仅是理解。对于开发人员系统管理员应用程序打包人员最终用户 .一般如何处理坏的 MSI 包 - 来自任何供应商或来源,而不仅仅是您自己的。

我认为现在是时候从另一个角度看待自我修复了。现在我终于可以写下我一直以来的意图了:开发人员对自我修复的看法 - 一些需要避免的陷阱自己的设置开发工作 - 经常使用 WiX 框架。只是一个简短的具体清单,列出了您的 MSI 程序包中不要做的事情。


MSI / WiX 设计缺陷导致自我修复问题

这是一个粗略的初稿。这些要点将在时间允许时充实。

  1. 你搞砸了 shared 运行 次 的安装。您不使用合并模块来部署全局注册的 and/or 共享 运行 时间文件。而是您安装自己的文件副本并在系统范围内注册它们。这对 COM 文件尤其不利,但也适用于其他类型的文件。冲突的应用程序将尝试恢复其状态,并且每次启动备用应用程序时都会产生“自我修复战斗”。

  2. 你运行进入空文件夹自修复特性。您创建一个具有目录键路径的空组件,而无需添加 CreateFolder 条目。这会导致 MSI 删除文件夹然后触发自我修复以将其放回原处的无限循环。此时 WiX 中可能有针对此的保护。

  3. 组件引用计数不正确。您自己创建了一个 软件包套件 ,它使用不同的组件 GUID 从不同的 MSI 设置将同名文件安装到磁盘上的相同位置。这很可能会触发自我修复,因为包“争斗”以将其文件版本放置到位。对此有几个“修复”,例如设计合并模块、使用 WiX 包含文件、安装没有引用计数的文件(空白组件 guid)-(更多细节将很快添加)。

  4. 错误的每用户文件安装。您将文件安装到用户配置文件并在 HKCU 中设置文件密钥路径而不是注册表密钥路径(MSI 设计指南要求)。这经常会导致普通用户经历重复的自我修复,但由于缺少磁盘权限而永远不会成功。普通用户看不到密钥文件,因为密钥文件所在的位置(另一个用户的用户配置文件)没有读取权限。这里有一个color illustration。而且除了一个link,图片形式还有:

  1. 错误的磁盘/注册表自定义权限。这个问题不同,但与上一个问题相似。您在安装期间应用自定义文件、文件夹和注册表权限,这会删除普通用户对安装位置的读取权限。普通用户会看到永远不会成功的重复自我修复。这也可能发生在“每台机器”文件位置,而不仅仅是用户配置文件路径(如上一期)。我听说有传言说有些人也看到了这种情况,特别是对于写保护的 ini 文件。

  2. 您为临时文件启用引用计数。出于某种疯狂的原因,您决定将文件安装到 tmp 文件夹或其他随时可能被清理的文件夹。也许您打算通过自定义操作或其他方式 运行 文件。在任何一种情况下,您都通过具有组件 GUID 和关键路径集的组件安装它,并且当文件从磁盘中“清除”时,您的 MSI 文件将尝试将其放回原处。每次“清理”文件时都会重复此操作。由于安装位置可能是每个用户的位置,其他用户可能无法从他们的登录中“看到”该文件,并且他们会立即经历重复的自我修复,而您只有在文件被“清理”时才能看到它。

  3. 恶意软件 - 真实和误报。您安装了 一个不寻常的二进制文件 而没有 运行 通过基本的病毒/恶意软件筛选来安装它。 检查实际恶意软件与检查误报一样重要(要使用的一种恶意软件扫描服务是 http://www.virustotal.com - almost 70 different scanners - pay special attention to the major vendors - obviously). So you ignore the malware check, and after deployment your product suffers false positives from several anti-virus vendors and self-repair will run in vain trying to put back the file only to have it "quarantined" again. Your customers blame you (funny how a false positive can be harder to get rid of than real malware?). The result is of course equally bad if you actually install a real virus or malware instead. The result is exactly the same - self-repair keeps running in vain. On the other hand, if the binary was infected after installation, then self-repair should serve its purpose and run once to put the clean file back in place. The major problem is that fixing a false positive is actually harder than dealing with malware (malware is of course worse for the customer if it causes data loss, but it is understood that this is out of your hands as software provider). With malware you simply tell your client to rebuild their PCs and reinstall your software, but with a false-positive you need to do something to whitelist your binary - often with several security software vendors. How do you deal with this process? As malware seems to become worse and worse and security is attempted tightened in any way possible, false positives are likely to become a major deployment problem - even more so than now. A lot of time can be wasted trying to get your binary whitelisted. And the obvious, but let's just say it out loud: don't brave this task on your own as a deployment person - this whitelisting is a huge task that requires management involvement. The problem affects everything for a software vendor: sales, development, marketing and support. As security software become more advanced and "smart" - they may start to quarantine the whole cached MSI on the system that is found in %SystemRoot%\Installer (used for maintenance installs, repair and uninstall). When this happens no self-repair will be possible - and also no uninstall (!) - unless you have access to the exact, original MSI that was used to install with. In these cases I suppose you could try some of the options listed here to get your MSI with malware or false-positives uninstalled: Why does MSI require the original .msi file to proceed with an uninstall? or section 12 here: Uninstalling an MSI file from the command line without using msiexec

  4. 您安装的桌面文件可能会被用户删除。这是一个“边缘案例”,要求您还错误地将安装组件的密钥路径设置为磁盘密钥路径(而不是正确的 HKCU 路径)。大多数时候你把快捷方式放在桌面上,这很好。但是,如果您安装了某种类型的数据文件,然后用户将其删除,则当您的应用程序通过广告快捷方式启动时,或者即使实例化了广​​告 COM 对象或特定文件类型,您也可以看到它通过自我修复放回原处已启动。

  5. 您将公布的快捷方式安装到“启动”文件夹。不要将广告的快捷方式安装到“启动”文件夹。它可以在每次系统启动时触发自我修复 运行,而根本不需要任何用户交互。据报道,删除快捷方式也会触发自我修复。这是我从未真正见过的东西,但它是有道理的。

  6. 您使用应用程序更改的 HKCU 密钥路径(或 HKLM)。您从 MSI 写入注册表的任何设置通常不应被修改,或者更糟的是,不应被您的应用程序操作删除。自我修复可能会导致。仅写入应用程序刚刚读取的数据。您的应用程序本身应始终将所有默认设置填充到 HKCU,并且您的设置不应干扰它们。用户配置文件也是如此。应该从每台机器的模板位置为每个用户复制它们。这个故事的总体寓意:仅部署每台机器的文件和设置 (HKLM)。其他一切都应由应用程序初始化:.

  7. 您的设置写入的注册表项会定期被组策略覆盖。我相信我第一次看到这个问题与使用 MSI 设置的 HKCU 中的某些 IE 代理设置键有关。出于很多原因,使用 MSI 来设置几个注册表项总是一个坏主意。请参阅此 serverfault.com 答案以获取几个问题的列表:MSI package for reg deployment(推荐快速阅读,虽然它与系统管理员最相关,但对开发人员来说很重要)。我无法重现这个问题,因为当关键路径丢失时会触发自我修复(通常不仅仅是更改或修改)。也许组策略实际上删除了 MSI 添加的 HKCU 值?我们确实看到了问题,所以这可能就是发生的事情。 总体信息:永远不要使用 MSI 来设置一些注册表项,尤其是当它们在 HKCU 中时。使用组策略、登录脚本、 VB 脚本、PowerShell 或其他更可靠的措施,例如让应用程序在启动时执行此操作(每个用户一次)。

  8. 您在 MSI 文件中注册了特定文件/MIME 关联或命令动词。大多数自我修复似乎是由产品之间的 COM 注册表干扰触发的,这些产品在 COM 对象实例化时触发自我修复,或调用广告快捷方式。但是,您也可以通过文件/MIME 关联和命令动词触发自我修复。特别是文件关联可以由系统上的其他应用程序/MSI 文件注册,这可能会触发非常持久的自我修复,因为每个应用程序都试图“窃取”文件关联。在您的 MSI 中谨慎使用这些功能 - 并确保您注册的文件关联确实是唯一的。切勿在 MSI 设置中设置“通用”文件关联(例如 jpg)。

  9. 同一个 MSI 错误地安装了两次(或更多次)。 这听起来很奇怪,但实际上可以通过多种方式实现。如果发生这种情况,自我修复可能不是您最大的问题,您还会看到其他问题:

    • 您忘记为重建的 MSI 生成新的包 GUID。 Windows 安装程序然后将两个不同的 MSI 文件“根据定义”视为同一文件。我相信在这些情况下我已经看到了自我修复,但你也会面临许多其他问题,同样很奇怪。始终自动生成包 GUID。任何两个 MSI 文件都没有理由具有相同的包 GUID(除非您正在 Windows 安装程序引擎中测试一些非常模糊的东西)。虽然充分意识到重复 GUID 的问题,但很多年前在一些非常忙碌的开发过程中使用 Installshield 时,我仍然遇到过这种情况。我仍然想知道它到底是怎么发生的——但它确实发生了。也许这是工具中的未知错误?
    • 一次失败的重大升级可能会同时安装两个版本的安装程序。您在 add/remove 程序中看到两个条目。在这些情况下可能会出现自我修复问题,但也会出现大量其他问题。根据我的经验,这个问题很严重,但还没有对两个 MSI 文件使用相同的包 GUID(上一个要点)那么糟糕。
    • 我敢肯定还有其他几种方法可以使同一产品最终被多次安装。也许 failed multi-instance transforms 也会导致问题?我不喜欢那个特定的概念,所以我还没有真正尝试过。

一些一般的“运行ner-up”自我修复相关问题:

  • 运行 MSI 验证和上述几个问题将被标记并轻松消除。
  • 永远不要 运行 MsiZap.exe 在你的开发者盒子或任何你不能轻易恢复的机器上。事实上,根本不要使用这个“工具”。在 MsiZap.exe 对 MSI 数据库的破坏造成的“脏状态”之上进行部署时,您经常会看到自我修复问题。
  • 如果您需要安装 COM shell 扩展,请确保在使用 Windows Explorer 时进行彻底测试,并在不同的视图模式之间切换以检查是否启动了自我修复。COM 对象如这基本上是连续使用,因此如果任何设置受到干扰,很可能(一定)自我修复。
  • 如果您将广告快捷方式单独放入功能中,它几乎不会触发自我修复。对快捷方式所在的功能及其所有父功能进行关键路径检查(上次我检查 ;-) - 那是几年前)。

自修相关答案(links 保管):