Wix 自定义卸载操作 - 如何在 msi 删除文件之前运行
Posted
技术标签:
【中文标题】Wix 自定义卸载操作 - 如何在 msi 删除文件之前运行【英文标题】:Wix custom uninstallation action - how to run before msi removing files 【发布时间】:2018-06-18 15:10:48 【问题描述】:我有一个将文件添加到安装目录的自定义操作。卸载程序时,另一个自定义操作会尝试删除这些文件,以便可以删除安装目录。
问题是我的自定义卸载操作在删除标准安装文件之后运行,因此安装目录保留在那里,尽管它是空的。
配置看起来像这样:
<CustomAction Id="AddFilesAction" BinaryKey="installerActions" DllEntry="AddFiles" Execute="deferred" Return="check" Impersonate="no" />
<CustomAction Id="CleanupAction" BinaryKey="installerActions" DllEntry="Cleanup" Execute="deferred" Return="check" Impersonate="no" />
<InstallExecuteSequence>
<Custom Action="CleanupAction" Before="InstallFiles">Installed</Custom>
<Custom Action="AddFilesAction" After="InstallFiles">NOT Installed</Custom>
</InstallExecuteSequence>
我可以在 msi 开始删除安装文件之前让CleanupAction
运行,这样自定义文件已经被删除并且 msi 可以删除主安装目录吗?
【问题讨论】:
【参考方案1】:问题是我的自定义卸载操作在删除标准安装文件后运行
那是因为您在 InstallFiles
之前安排了它,它在 standard InstallExecuteSequence
中的 RemoveFiles
之后。您还可以在 Orca 或 InstEd 等编辑器中打开 MSI 文件,然后查看InstallExecuteSequence
表。按Sequence
列排序以查看执行顺序。
我可以在 msi 开始删除之前让 CleanupAction 运行吗 安装文件
当然,在RemoveFiles
之前安排:
<Custom Action="CleanupAction" Before="RemoveFiles">
(REMOVE~="ALL") AND (NOT UPGRADINGPRODUCTCODE)
</Custom>
编辑:在 Stein Åsmul 让我意识到之后,我还改进了自定义操作条件。 See his answer详细推理。
如果您还不知道,WiX 已经支持删除应用程序生成的文件,这些文件可能能够替换您的自定义操作。它以RemoveFile
和util:RemoveFolderEx
元素的形式出现。
如果这些不能满足您的需求,因此您仍然需要自定义操作,我建议在运行时将要删除的文件的临时记录添加到 RemoveFile
表中(在 立即 em> 自定义操作!)。这为您提供了使用 MSI 引擎进行实际文件删除的好处,即。 e.如果用户决定取消卸载或发生错误时自动回滚。我过去曾这样做过(在发明RemoveFolderEx
之前),所以如果您需要更多信息,请再问一个问题。
【讨论】:
完美。谢谢你。添加临时记录听起来很有趣,如果我无法弄清楚,我会添加另一个问题。谢谢 顺便说一句,我尝试用 RemoveFolderEx 替换自定义清理操作,但它的工作方式与在 RemoveFiles 之后运行我的清理操作时相同。该文件夹(实际上是安装文件夹内的一个子文件夹)已被删除,但卸载完成后根安装文件夹(现在为空)仍然存在。不知道为什么。 @FrantišekŽiačik 尝试将<RemoveFolder Id="RemoveRootDir" On="uninstall"/>
元素添加到位于根安装文件夹中的组件。
是的,这行得通,虽然对我来说它看起来有点 hacky。【参考方案2】:
简答:您的情况和顺序似乎有误。请安排您的清理自定义操作在 RemoveFiles
之前运行,并且可能设置一个更好的条件以使该操作仅在需要时运行(而不是在意外的设置模式下)。下面我建议(REMOVE~="ALL") AND (NOT UPGRADINGPRODUCTCODE)
。如果您使用此条件,请彻底测试。 下面会解释这种情况。
快速示例:
<InstallExecuteSequence>
<Custom Action="CleanupAction"
Before="RemoveFiles">(REMOVE~="ALL") AND (NOT UPGRADINGPRODUCTCODE)</Custom>
</InstallExecuteSequence>
请务必阅读以下详细信息。您可能还想收紧复制文件操作的条件 - 因为它也会在主要升级时运行 - 这可能是您想要的,也可能不是。
自定义操作替代方法:Please avoid custom actions if you can - 一些自定义操作问题的总结 - 它们很严重)。自定义操作是部署失败的主要原因。你确定你需要它们吗?通常还有其他方法可以使用内置的 MSI 功能或特定于 WiX 的构造来实现您在自定义操作中实现的内容。常见的例子是:安装服务、删除文件、更新 XML 文件或 INI 文件等......但有时自定义操作是必要的 - 显然。 Zett42 has already written well about the alternatives,所以我不会在这里重复 - 请检查他/她的答案。
RemoveFiles:这里还有更多问题 - 我将在下面尝试描述这些 - 但是在标准操作时会卸载文件RemoveFiles
强>运行。换句话说,您需要在InstallExecuteSequence
中安排在此标准操作之前运行的清理自定义操作。
条件:您的清理自定义操作条件 Installed
将使自定义操作在 modify
、repair
上运行和 minor upgrade patching
以及 uninstall
和 major upgrade initiated uninstalls
。这很可能不是您想要的。要指定仅在卸载时运行,最常见的条件是 REMOVE~="ALL"
。这将使清理发生在手动启动的卸载和重大升级启动的卸载(不是你想要的我想的那样)上。您可以尝试(REMOVE~="ALL") AND (NOT UPGRADINGPRODUCTCODE)
(仅在常规卸载时运行 - 而不是在重大升级卸载时运行)。
提示:条件很容易搞砸 - 即使对于有经验的 WiX / MSI 用户也是如此。一些可能有帮助的资源:
Common MSI Conditions Cheat Sheet(来自 Installshield,hotlink to actual PDF) How to add a WiX custom action that happens only on uninstall (via MSI)?(有用的概述,一些小问题或难以解释的细节 - 尤其是与REMOVE
属性相关的 - 但总的来说可以作为概述和速成课程)
一些进一步的链接(供参考):
Wix Tools update uses old custom actions(分析了一些奇怪的情况) WIX Installer: Prevent installation on Windows Server 2012 R2(您可以在调试期间使用 VBScript 来分析运行时的条件 - 在序列中的这一点是否正确? - 可以非常有效地进行测试和调试 - 证明是在布丁中 - 底部示例:“Property Debugger Demo” - 和 a newer sample here with actual code) Is it possible to run a custom action only in repair mode http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/Conditions-for-Uninstall-Remove-Only-td4834010.html【讨论】:
感谢其他观点。我们使用自定义操作有两个原因。客户必须在安装过程中选择一个 zip 文件,该文件必须在安装目录中解压缩。第二个是我们需要更新java属性文件(不是ini文件)。 很好地捕捉到不正确的自定义操作条件。 顺便说一句,我已经修复了产品 ID(例如Id="SOME-GUID"
而不是 Id="*"
),因为我需要能够在像 msiexec /x SOME-GUID
这样的脚本中进行自动卸载。但这样一来,我认为它不允许我进行升级。
您需要更改产品 GUID 才能对您的包进行重大升级。你只使用minor upgrades 吗? query a machine to determine what MSI packages are installed (to find the product GUID) 相对容易 - 如果您的 AD 设置正确,即使是远程也是如此。 Here is a blurb on retrieving upgrade codes from remote machines.【参考方案3】:
我不会在 InstallInitialize 和 InstallFinalize 之间安排您的操作。将您的文件放在 Initialize 之前,并在 Finalize 之后清理您的文件。请注意,您将在 InstallFinalize 之后丢失您的属性值,并且您需要考虑这一点。
【讨论】:
自定义操作在InstallFinalize
之后或InstallInitialize
之前运行将不会提升,因此在尝试执行特权操作时可能会出现错误消息 - 除非整个设置是从命令提示符启动的具有管理员权限(或等效机制)。 以提升的权限运行意味着标准用户在安装期间以临时管理员权限运行(在 InstallInitialize 和 InstallFinalize 之间),而 以“真正的”管理员权限启动的安装程序表示整个过程以管理员权限运行。企业部署使用提升的权限。
在InstallInitialize
和InstallFinalize
之间定义的“事务”之外更改系统也违反了Windows Installer 最佳实践。对系统的所有更改都将按此顺序执行,如果安装失败,应正确回滚更改。坦率地说,我不知道为什么可以在 InstallFinalize
之后插入自定义操作 - 你不能在那里插入 deferred mode custom actions
,但可以插入 immediate mode custom actions
。以上是关于Wix 自定义卸载操作 - 如何在 msi 删除文件之前运行的主要内容,如果未能解决你的问题,请参考以下文章
WiX 3.8:使用相同注册表值的两个MSI。如果同时卸载两个MSI,如何删除注册表值?