如何使用WiX将CustomActionData传递给CustomAction?

69

如何在 CustomActionData 上设置属性以便通过延迟的自定义操作检索?


3个回答

156

延迟自定义操作无法直接访问安装程序属性(参考文献)。事实上,只有CustomActionData属性。

session.CustomActionData

在会话对象上,还有其他方法和属性,可以在此处列出。

因此,如果想要使用延迟的自定义操作检索属性(例如INSTALLLOCATION),您必须使用类型 51 自定义操作(即设置属性自定义操作)来传递信息,然后通过session.CustomActionData从 CustomAction 的 C# 代码中消耗数据(参见参考参考)。

以下是一个类型 51 自定义操作的示例(CustomAction1),它将设置一个属性,在CustomAction2中可以检索该属性。

<CustomAction Id="CustomAction1"
              Property="CustomAction2"
              Value="SomeCustomActionDataKey=[INSTALLLOCATION]"
/>

请注意Property属性名称为CustomAction2。这很重要。类型为51的操作的Property属性值必须等同于正在消费CustomActionData的自定义操作的名称。(参见参考资料

请注意Value属性键/值对中的名称SomeCustomActionDataKey。在您的C#代码中,消费自定义操作(CustomAction2)将使用以下表达式从CustomActionData查找该属性:

string somedata = session.CustomActionData["SomeCustomActionDataKey"];
Retrieving values from `CustomActionData` requires using the key from the `key=value` pair in the `Value` attribute, not the value in the `Property` attribute of the type 51 custom action. It's important to note that although `CustomActionData` is populated by setting an installer property with the same name as the Id of the consuming custom action, the keys in `CustomActionData` are not installer properties. See this reference for more information.
In our scenario, the consuming custom action is a deferred custom action defined similarly to the example below:
<Binary Id="SomeIdForYourBinary" SourceFile="SomePathToYourDll" />
<CustomAction Id="CustomAction2"
              BinaryKey="SomeIdForYourBinary"
              DllEntry="YourCustomActionMethodName"
              Execute="deferred"
              Return="check"
              HideTarget="no"
/>

配置InstallExecuteSequence

当然,在类型51的自定义操作(CustomAction1)之后,消费自定义操作(CustomAction2)必须运行。因此,您需要按照以下方式安排它们的计划:

<InstallExecuteSequence>
  <!--Schedule the execution of the custom actions in the install sequence.-->
  <Custom Action="CustomAction1" Before="CustomAction2" />
  <Custom Action="CustomAction2" After="[SomeInstallerAction]" />      
</InstallExecuteSequence>

5
Alexey,感谢你抽出时间来写这篇文章。这对我真的很有帮助。不幸的是,我只能给你一个+1… - Tim Long
1
正如@TimLong所说,非常感谢。多希望我能够点赞这个很多很多次。 - Lynn Crumbling
15
如果你需要传递多个参数,你不能添加另一个CustomAction,它们会被覆盖,但你应该使用分号将参数分隔开来进行设置:Value="ActionDataKey1=Value1;ActionDataKey2=Value2" - Marco Ciambrone
1
您不必遵循键值对格式,可以提供 任何 字符串值,并使用 session.CustomActionData.ToString() 读取它。 - rustyx
1
我在寻找ASP.NET MVC Core安装后将设置写入appsettings.Json文件的解决方案时偶然发现了这个问题。我编写了一个CustomAction来完成它,但是在安装期间尝试写入设置文件时遇到了权限问题而失败了。唯一的方法是推迟执行,但我无法访问会话对象。我尝试使用CustomActionData,但我移植的示例代码设置不正确。您的示例是正确的方式。非常感谢! - Francis
显示剩余3条评论

11

对于我们这些C++菜鸟,您可以按如下方式检索属性:

MsiGetProperty(hInstall, "CustomActionData", buf, &buflen);

然后解析“buf”。感谢Bondbhai


5
如果传递给自定义操作的值不是键/值对集合...

<SetProperty Id="CustomAction1" Before="CustomAction1" Value="data" Sequence="execute"/>
<CustomAction Id="CustomAction1" BinaryKey="BinaryId" DllEntry="MethodName" Execute="deferred"/>

如果想要检索整个 Blob,则可以使用以下代码:

string data = session["CustomActionData"];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接