自我修复,简单易懂的解释: 删除文件后,为什么MSI安装程序会重新配置?
针对WiX / MSI文件的具体设计建议
我一直试图写关于开发人员的重复MSI自我修复,但最终得到了过多的细节。这里是我最后的尝试:具体的设计建议,告诉你如何避免在您的WiX / MSI文件中犯错。
下面的答案提供了一个检查清单,用于解决任何来源的自我修复场景,不仅仅是您自己的包。查看上面链接的答案,以了解您自己的MSI包设计问题。
“简版” - 自我修复清单
要永久可靠地解决所有人的自我修复问题,必须有开发人员和安装程序开发人员参与,因为真正的解决必须在供应商级别上进行。
如果您处于企业环境,则应该涉及您的应用打包人员,以确定问题是来自供应商还是其他原因导致的不良应用程序重新打包。
系统管理员必须知道他们正在查看什么,当没有可用的修复方法时,使用各种变通方法来处理野外中的问题。即使最终用户也可以尝试一些简单的变通方法(请参见第5节)。
自我修复问题的实质:
大多数自我修复问题与COM相关,对于供应商和开发人员有两种一般性修复方法:1)使用通过合并模块通常部署的正确部署的共享COM库,或2)使用无需注册的COM来“屏蔽”应用程序免受自我修复和兼容性问题的影响。
您的安装程序开发人员可以实现合并模块修复,必须进行开发人员测试。合并模块是用于共享文件的标准化共享部署库。
仅在我的经验中,无需注册的COM需要开发人员参与。如果开发人员需要使用特定版本的COM文件(出于任何原因),则此选项尤其相关。详情请参见下面的第5.4节。
除了COM之外,您的安装程序开发人员还可以通过在您的MSI安装程序中注册文件和MIME关联和命令动词来引起自我修复问题。请谨慎使用,并确保您的文件/ MIME关联是唯一的。
最后,您还可以通过两个已安装的MSI文件之间任何文件或注册表冲突而导致自我修复。它们“错误地共享资源”,并将其视为自己的资源-直到解决冲突为止。
某些自我修复问题并不是由供应商应用程序或设置中的错误引起的,而是由计算机环境中的外部因素引起的,例如来自胡乱更改的用户、脚本、病毒、防病毒软件或安全软件的干扰。有关更多详细信息,请参见第3节。
如果您确定所看到的自我修复是仅由MSI引起的(而不是其他外部原因,如下面的前几个部分中所述),则可以跳转到第5节以获取建议的修复和解决方法列表。
在第5节中提出的大多数“解决方案”实际上都是主要是系统管理员技巧,并不能解决根本问题-如上所述,真正的解决方案必须来自供应商。例外是“5.4:无需注册COM”,它确实可以帮助开发人员“屏蔽”其应用程序免受自我修复问题的影响。
如果您没有计算机管理员权限,则建议尝试“解决方案”5.2、5.3或5.1(通常需要管理员权限尝试5.1,但它很简单)。这些都是“快速解决方法”,其他方法则更加复杂。如果这些解决方法不起作用,请请求您的管理员阅读其他建议。
我之前详细讨论过这个问题,但它过于关注理解问题而非找到可接受的解决方案。你可以在此处阅读有关自我修复问题的完整解释:
如何确定导致重复 Windows Installer 自我修复的原因?。
修复 Windows Installer 自我修复问题
为了真正解决反复和无休止的自我修复问题,您可以尝试以下建议(按照复杂度和难度逐步增加)。在执行这些操作之前,您应该确认自我修复问题的真实来源。它可能不是由 MSI 文件引起的,而是由其他外部原因引起的(例如脚本或用户删除文件或反病毒软件阻止文件)。
如果问题确实与 MSI 相关,则可以尝试禁用广告快捷方式和COM 加载项、使用注册表无 COM、向应用程序供应商寻求帮助、卸载有问题的应用程序、虚拟化包或者全面修改缓存的 MSI 数据库和注册表(不建议这样做,只有在专家的帮助下才能实现)。这完全取决于您的情况。如果脚本等外部原因导致问题,则必须消除此干扰。请参阅下面的详细信息-只需按照检查清单操作即可。
解决问题的第一步是确定该问题确实存在于您的平台上,并确定哪些应用程序首先触发了自我修复:
1. 确认问题确实存在于您的环境中。
- 通常情况下,我们可以确定问题的原因并使用多种可行的解决方法来应对自我修复的问题。然而,有时候很难找到一个好的、永久性的解决方案(除非在下面所述的情况下获得了供应商的帮助)。
- 如果你是一名系统管理员正在寻找自我修复问题的解决方案,请确保这个问题不仅出现在一台计算机上——尤其是当你在开发者、QA甚至测试计算机上遇到该问题时。
- 如果你只在一台计算机上看到自我修复问题,那么另一种选择可能是重建这台计算机,而不是“解决”该问题。但你有相当高的风险再次看到这个问题。如果问我,不要重建,因为这不是解决方案——但我猜在现实世界中经常会这样做。
- 请注意,对于桌面支持而言,一个通过AD广告发布的MSI安装程序可能安装速度缓慢,并且被用户反复中止,这看起来像是自我修复问题,但这是MSI的预期行为。让安装程序完成一次(可以更改安装程序进度条来禁用取消按钮——例如使用
msiexec.exe /I "MyApp.msi" /QB-!
来仅显示进度条、没有取消按钮和末尾的模态对话框)。
2. 确定造成自我修复的罪魁祸首
- 通常情况下,至少有两个应用程序会发生冲突(它们错误地共享某些资源),因此很可能是由多个应用程序导致了问题,而不是单个应用程序。
- 自我修复的触发器通常可以在发生自我修复的系统的事件查看器中找到。按照以下步骤打开事件查看器:
- 右键单击 "我的电脑"
- 点击 "管理"
- 如果弹出用户账户控制提示,请点击 "继续"
- 进入 "事件查看器" 部分,检查 "Windows 日志"
- 通过查看事件日志中的 "应用程序部分",您可以找到 ID 1001 和 1004 的 MsiInstaller 事件源,并确定造成问题的应用程序。
3. 确认外部非 MSI 原因不是问题的根本原因
- 删除文件或注册表设置的任何操作,无论是手动还是自动,都可能触发MSI自我修复。尤其是在用户配置文件或注册表的HKCU部分中删除内容时。
- 在大多数情况下,这些触发器只会导致单个自我修复运行,然后问题得到解决(这就是自我修复的预期工作方式,帮助用户)。允许自我修复运行一次,然后再次启动应用程序以测试问题是否已经解决。此后,您的应用程序应该可以正确启动。
- 特殊情况:具有讽刺意味的是,有时通过将应用程序的HKCU应用程序键(在注册表的用户部分中)重命名为实际强制自我修复运行并将应用程序的默认数据安装在用户配置文件中,可以修复破损的应用程序 - 如果该数据被意外删除了(这种修复通常不适用于终端服务器)。
- 如果同一个文件或注册表条目再次被自动手段删除并导致自我修复结果,则必须消除或更新导致此问题的自动进程,然后问题就解决了,您可以停止阅读。如果您自己再次手动删除了该文件,则可能会存在记忆力问题 :-)。
- 总之,清理脚本、登录脚本、清理应用程序或操作过度的用户都可能导致这种自我修复。
- 最后,病毒和反病毒软件(以及其他安全软件)可能会阻止访问文件并触发永远无法成功的自我修复。
- 对于受感染的计算机,请重新构建计算机。总体而言,这将节省您的时间。
- 对于反病毒/安全软件问题,请寻求安全人员解决。在某些情况下,他们可能需要联系供应商(尤其是针对误报)。
- 无论是病毒还是反病毒相关的问题,都可以在http://www.virustotal.com上检查有问题的文件,以验证它是否实际上是病毒还是误报(这对于自我修复来说可能是更大的问题)。
- 就我个人而言,我曾经看到过几个与反病毒/安全软件相关的自我修复问题,但没有真正与病毒相关的问题(到目前为止)。我想病毒通常会感染核心系统文件而不是应用程序文件,并且核心系统文件不应由MSI文件部署(共享系统文件可能包含在MSI文件中,但不包括核心系统文件)。
- 联系供应商(或您自己的打包部门)。
5. 选择一个“变通方法”或解决办法来处理冲突情况。
If the vendor(s) won't provide a fixed installer package, you need to find a "workaround" to deal with the situation. There are several options, and some "quick workarounds" should be tried before you delve into too much complexity. Here are some problem solving suggestions in order of increasing levels of difficulty and complexity:
5.1: Just uninstall the culprit(s).
- The absolute simplest fix is to figure out what application(s) trigger(s) the self-repair and just uninstall it, if that is an acceptable solution for your environment (it rarely is).
- This can be acceptable if there are two (or more) applications in conflict and one of them is rarely used or "optional".
- You can run the problem application on a virtual machine instead (see section 5.5). This would be my preferred "fix" for a very "misbehaving" application. All problems should disappear without any real debugging (which is costly).
- Plain uninstall is an option that is at least worth considering - some software can be very problematic in more ways than one, and should simply be rejected for use. Be sure to let the vendor know that the software was rejected as well. It might be the only way to make them take the problem seriously.
5.2: Remove Advertised Shortcuts.
- The first Windows Installer workaround to try is to remove "advertised shortcuts" (essentially a special type of shortcut that points to an Windows Installer application feature, and not directly to an executable or file). Read the linked article from Symantec for details on advertised shortcuts.
- Note that shortcuts can be created "anywhere" including in special folders such as the "Startup" folder. This particular location means a self-repair can be triggered by itself on system startup (without user interaction).
- Use an MSI viewer tool and open the system-cached MSI and inspect its Shortcut table to find all shortcuts. In order to find a list of all cached packages you can try this answer: How can I find the product GUID of an installed MSI setup? (open the package path specified in "LocalPackage").
- You then re-create a regular shortcut that points directly to the executable in question. This will "bypass" the most common trigger of self-repair (the advertised shortcut). In some cases this avoids the whole self-repair issue. It is worth a try.
- Be aware that even if this appears to work straight away, self-repair might still re-appear whilst you work inside the application (for example when you open a particular form). You need to "pilot" this fix with some users who actually use the application actively to make sure it is a good enough workaround for your environment.
- You have also merely eliminated the symptom of the problem, the registry or file conflict that caused it has merely been "bypassed" or "silenced" - it still exists, but this may be good enough if the applications exhibit no problems during operation.
- There is in fact a way to disable all advertised shortcuts on installation of any MSI package. You set the property DISABLEADVTSHORTCUTS (in one of the ways described in the link), and then all shortcuts will be created as regular shortcuts and they will not trigger self-repair. There are at least two problems:
- 1) The package could be designed to use self-repair to install userprofile files or HKCU settings. In this case this data will then never be added to the system as intended since self-repair will never run, and the install is effectively incomplete.
- 2) There is no guarantee that self-repair won't still occur - since it can be triggered by other advertised entry points such as COM invocation, file and MIME associations and command verbs.
5.3: Disable COM addins (if possible).
- If your problem is related to the loading of an add-in (for Outlook, Excel, Word or other apps like AutoCAD or similar), then there are no shortcuts to tweak - the addin is loaded on launch of its "host application".
- The easiest to try is to disable any addins you don't need in the addins dialog of the application in question (often Outlook, Excel or Word or similar) and see if this makes the problem go away. In some cases you are just disabling COM addins that users never used in the first place, and the problem has been eliminated.
- And, rather obviously, also try to disable addins that you actually need as well, in order to check if the problem can be related to its loading. If the addin is the culprit, you should continue down the check list to the next proposed solutions (next bullet points).
- I should re-iterate that the preferred solution would be a fix from the vendor (most often it would involve making the addin properly use the latest, shared ActiveX/OCX controls in question - other addins could still trigger the problem though, if they are also badly designed. You could end up dealing with multiple vendors - usually blaming each other).
- In fairness to the vendors, the problem can also be caused by bad corporate application repackaging - if you are on a corporate machine. Then you must deal with the packaging department for a fix.
5.4: Try registration-less COM
- Arguably this solution is more complicated than virtualization (which is described in the next bullet point), but I put it here since it might be a preferred option for some people.
- Registration-less COM is something I have rarely used, but it is said to be a viable solution: Generate manifest files for registration-free COM. This essentially bypasses the registry and activates private copies of the COM files controlled by manifest file(s) placed next to the application executable(s) - effectively shielding the application from COM registry interference (in theory). "Everything happens in the same folder".
- Your in-house packaging department might be able to use this to deal with "difficult vendor packages" to "isolate" their problems. However, I am not convinced registration-less COM will work properly without a few additional application tweaks contributed by the original solution developer, but I lack the empirical data to back it up. If it is an in-house app with source available, give it a test spin (and let us know).
- My main problem with this approach, is that it opens up potential security holes (private copies of COM files that will never be patched by Microsoft), if you don't make sure the isolated components are updated yourself. Updates would likely cause lots of manifest-rewrite work as well (but are these old COM files updated at all anymore anyway?)
- Note that registration-less COM, at least in theory, can be used for all COM related conflicts, whether they are VB6 executables, VC++ applications that use COM, etc... I am honestly not sure if it works properly for (office) COM addins (dlls) and VBA forms.
- Here is what appears to be one of the better MSDN articles on registration-less COM): https://msdn.microsoft.com/en-us/library/ms973913.aspx (there is even a downloadable MSI with the samples - which ironically seems to trigger an error for me on launch).
- Personally I would probably rather try a virtual package using APP-V rather than trying to use registration-less COM (see next bullet point).
- It should be re-iterated that rather than "shielding" your own application - the correct vendor fix is to stop deploying private copies of shared COM files that are erroneously registered system-wide, and start installing them as intended using the appropriate merge module for deployment.
5.5: Virtualization (APP-V, Virtual Machine, etc...).
- Apart from uninstalling or disabling components, the simplest fix is arguably to use virtualization to "isolate" the applications that conflict. If you still want the applications on your main SOE (Standard Operating Environment), you could try to use a virtual deployment package (APP-V). This is an application that is basically installed on demand (on launch) and runs "sandboxed" or isolated from other applications on the system.
- You can also use a virtual machine via systems such as VMWare or Microsoft Virtual PC to run the problematic application(s) in their own operating system. Often people have admin rights when using virtual machines, but don't on their main SOE system (main workstation). Many developer applications are more effective to use with admin rights, so this solution might be particularly useful when dealing with development teams and their requirements.
5.6: Windows Installer tweaking - (Experts only!).
- If the problem is very serious for your desktop environment and none of the options above work, you can try to fix the problem at a Windows Installer level. It might be worth it if the addin (or whatever other software) is crucial to have available on the company's main PC environment.
- Essentially what you need to do is remove offending entries from the system cached MSI and/or the registry (disable advertised entry points such as advertised shortcuts, COM registration, file associations, MIME associations or command verbs, etc...).
- This is very involved and not good practice to do, and there are some side-effects (for uninstall, resiliency, etc...), but it is the only "last resort" that I know about.
- In these cases you would be advised to contact a deployment / Windows Installer expert and have them analyze whether a "fix" is possible. It can work, but don't expect miracles.
- If you insist on debugging yourself, you need to get hold of a tool to open cached MSI files on the system (such as Orca, Installshield, Advanced Installer or similar) and you need to "hack" the database - not recommended.
5.7: Windows Installer zapping - (Not safe!).
I am including this "option" for completeness and "historical purposes" if you like. It was never a good option, and is now very unsafe on newer versions of Windows.
MsiZap.exe was a Microsoft SDK tool meant as a last-resort tool for developers to clean out failed MSI installs or uninstalls, it was never intended for widespread use. It allowed the complete "dirty unregistration" of any MSI package. MsiZap.exe is now deprecated, unsupported and unsafe to use. Use only on throwaway virtuals, if at all.
Back in the day a common "system administrator trick" was to use MsiZap.exe to "zap" a whole Windows Installer package from the system. Besides leaving your system incurably dirty, it also removed all self-repair problems for that application.
The junk that is left behind after running MsiZap.exe includes essentially everything (except the actual MSI database registration). All files, all registry entries (including COM), SharedDll ref counters (which really screw up things on reinstall), services, anything really. You will never be able to uninstall properly. In most cases you will fail to install upgraded versions of the same application without side effects. Many people actually see more self-repair problems afterwards when trying to install on top of the dirty state.
Rob Mensching, creator of WiX, Orca and all things Windows Installer has a blog post on the perils of MsiZap. MSDN describes another bad side effect: All program update information is removed when you use the Msizap.exe tool to uninstall a program from a Windows-based computer
6. 总结与结论
- 第四步 - 联系供应商以修复问题 - 是我认为唯一的"真正的解决方法"。
- 所有其他提议都试图处理由供应商错误导致的问题,而不是提供持久的解决方案。
- 现实世界中的问题是,许多供应商往往彼此指责,因此您可能会运气不佳。有些做得对的供应商也会受到其他人的设计错误的影响。
- 提议5.1、5.2、5.3是简单易行的“变通方法”。
- 任何人都可以尝试,应该是安全的。
- 提议5.2和5.3甚至可以在没有管理员权限的情况下尝试。
- 提议5.4 - 无需注册的COM对象 - 是一个相当复杂的、潜在的“解决方法”。
- 可能需要开发者参与,找出所有相关文件进行“隔离”。
- 根据我的经验,这种项目即使有专家的帮助,也需要花费数天的时间来尝试,而且没有真正的保证它最终会起作用。
- 专家们对此持有不同的看法,有些人成功了,有些人说失败了。那些能够访问解决方案源代码的人似乎都成功了。
- 就我个人而言,我不喜欢它可能开放的安全漏洞,任何新文件版本的部署都可能意味着重新编写清单(我相信)。
- 然而,这些COM对象现在已经如此古老了,以至于它们不太可能得到任何安全更新。我想这些COM对象现在主要用于.NET互操作。
- 提议5.5 - 虚拟化 - 是一个常见的选择,如果环境中可用,应该在5.4之前尝试。俗话说,“虚拟化,认真对待”。
- 老实说,我不知道(缺乏经验)虚拟化是否适用于(办公室)插件。如果您可以确认,请更新。
- 可执行文件肯定可以进行虚拟化。
- 提议5.6 - “缓存的MSI调整” - 是一个“hack”,如果由部署专家正确执行,可以“足够好”。
- 有一些“副作用”,特别是对于卸载 - 以及“弹性”,但如果做得正确,这些应该是可管理的。
- 这就是“现实世界”-没有什么是“干净的”。
提议5.7 - “清除MSI” - 是不安全的、已弃用的“传统hack”。
由于系统的“脏状态”,存在几个副作用。
据报道,在