WiX:基于另一个 CustomAction 的结果的 CustomAction

WiX: CustomAction based on the outcome of another CustomAction

我对 WiX 还很陌生,所以我问的问题可能非常直截了当,但我在 google 上找不到太多帮助。

我想执行 2 个自定义操作,比如 ca1 和 ca2,其中 ca2 的执行取决于 ca1 的结果,如下所示:

if ( ca1 == SUCCESS )
{
  Perform ca2
}

所以只有当我的 ca1 returns 成功(没有失败)时才应该执行 ca2。

在 WiX 中执行此操作的最简单方法是什么?

你描述的是默认的。如果自定义操作失败,安装将中止,之后只能执行回滚操作。因此,为了使您的问题有意义,首先您必须忽略或以其他方式掩盖您的第一个自定义操作的失败。

其次,一个动作知道另一个动作的 return 结果的唯一方法是它是否通过调用 MsiDoAction (或其某些包装器)来调用它。这样做会模糊自定义操作之间的界限,因此我假设这不是您描述的情况。

剩下第三种也是最后一种方式:寻找外部沟通渠道。对于立即行动,我建议 ca1 在成功(调用 MsiSetProperty or a wrapper like DTF's session[property]), and ca2 either reads (MsiGetProperty / MsiEvaluateCondition)时设置 属性,或者直接根据 属性 的值设置条件。对于延迟操作,属性不会传播,因此您必须确定其他一些渠道。 (也许提前选择路径的临时文件会起作用。)

但整个场景对于 Windows 安装程序来说有点不寻常;我会建议避免它。也许合并您的操作,以便在冒泡回到序列之前可以处理任何失败场景 "internally"。或者您的具体操作可能会导致更具体的建议。

将第一个自定义操作设置为 属性。如果 属性 存在或设置为预期值,则仅 运行 第二个自定义操作。

您绝不能使用即时模式自定义操作对系统进行更改。当设置由具有提升权限的受限用户执行时,它们永远不会 运行 正确(即时模式操作永远不会提升,它们总是模拟用户,因此您尝试更改的任何内容都会触发访问被拒绝)。此外,它们可能无法在静默执行模式下 运行,具体取决于您的排序(例如,如果您尝试从设置 GUI 调用它们)。

Michael Urman 谈到的自定义操作之间的另一个“外部通信渠道”可能是 HKLM 中的注册表项,您可以写入然后读回。

但是,真正的解决方案是尝试 WiX 的内置防火墙功能。它由知识渊博的 MSI 专家可靠地编写,并支持适当的回滚。它将远远优于任何人可以自己滚动的东西: http://wixtoolset.org/documentation/manual/v3/xsd/firewall/firewallexception.html

来自 WiX 文档here

    <InstallExecuteSequence>
         <Custom Action='FooAction1' After='InstallFiles'/>
         <Custom Action='FooAction2' After='FooAction1' Condition='FOOACTION1SUCCESS'/>
    </InstallExecuteSequence>

让 FooAction1 中的代码设置 属性 MsiSetProperty('FOOACTION1SUCCESS', '1') 现在 FooAction2 将仅在设置 FOOACTION1SUCCESS 属性 时 运行。但实际上 Michael Urman 的回答是正确的。您应该在一个自定义操作中处理所有异常。