我有两个共享同一组注册表值的MSI应用程序( app1.msi 和 app2.msi )。两个MSI都引用了一个包含所有自定义操作和内容的dll。我正在使用WiX 3.8。这些注册表值是解决方案的自定义。
我需要找到卸载过程的方法,只有在删除两个应用程序时才删除注册表值。现在,每当我删除 app1 或 app2 时,注册表值都会被删除,除非我卸载并重新安装,否则其他应用程序将无法使用。
关于如何解决这个问题的任何想法?
答案 0 :(得分:4)
这是一个非常常见的问题。问题是你的MSI设置都认为他们“拥有”有问题的文件和注册表项,所以他们很乐意在卸载时删除它们 - 这显然很明显。现在该怎么办呢?
解决方案通常是使用相同的组件GUID在两个设置中安装注册表项/文件。实际上,这意味着组件被注册为共享组件。 MSI的内置机制是“merge modules”(你可以build merge modules with WiX)。您还应该能够使用WiX包含文件 - 但我必须承认我从未花时间去实际尝试它。基本上这需要将一个组件放入一个WiX源文件中,然后由两个设置包含,如下所示(使用WiX中的预处理器功能):How to include wxi file into wxs?。
在两个MSI文件中使用相同的组件GUID后,在安装两个产品时,它的引用计数将为2。卸载一个产品时,引用计数将减少为1,因此不会卸载该组件。卸载第二个产品后,一旦达到0,它将被卸载(除非它被标记为永久组件)。
了解组件引用计数是理解MSI的关键。这里有一个答案,如果你花时间仔细阅读它可能会有所帮助(我想我推荐这个 - 请给它一次性): Change my component GUID in wix? (请仔细阅读此答案,看看是否仍有意义。)
现在进一步的复杂化:“在野外”部署旧的MSI文件意味着从现在开始设置稳定的组件GUID并不一定有助于解决问题,因为在安装新的MSI时会卸载旧的MSI MSI仍然认为它在卸载时“拥有”了注册表项 - 因此将删除它。只有当您的设置“知道”该组件已共享且其注册表项应保持不变时,才能解决该问题。
在我详细说明之前,这些MSI文件是否存在?正如在野外发表,还是你还在发展中?
要超越自己:如果您可以更改注册表项的位置(例如,从function handle_response(response) {
if (response["unlocked"]) {
activate_slider(reset_slider); // ideally reset_slider() comes here
} else {
error(response["message"]);
reset_slider();
}
}
function activate_slider(cb) {
setLocked(false);
setTimeout(function () {
setLocked(true);
cb();
}, 3000)
}
到HKLM\Software\Company\MyProduct
- 这通常是不可能的),然后还要为其设置新的组件GUID它,那么你应该从过去的罪中“解耦”,你的新MSI文件应该正确地共享组件。
说了这么多,我想问一下这些注册机构设置是在HKCU还是在HKLM?通常不建议将设置写入HKCU表单MSI设置 - 您应该在首次启动应用程序时填充HKCU。这种方法可以解决许多难以部署的问题 - 或者阻止它们存在。