WIX Toolset:多CustomAction下传递CustomActionData失败排查
我需要给WIX Toolset MSI的第二个自定义动作(CA)传递多个属性,按照相关方案配置后,实际获取到的属性值为空,以下是我的配置和代码,请帮忙排查问题:
Product.wxs配置
<Binary Id="CustomAction1" SourceFile="..\CustomAction1\bin\Debug\CustomAction1.dll"/> <Binary Id="BinaryId1" SourceFile="..\CustomAction2\bin\Debug\CustomAction2.dll"/> <CustomAction Id="CustomAction1" BinaryKey="CustomAction1" Execute="immediate" DllEntry="CustomAction1" /> <CustomAction Id="PrepCustomAction" Property="CustomAction2" Value="PROPERTY1=[NAME];PROPERTY2=[TRUST];PROPERTY3=[LOGIN];PROPERTY4=[PASSWORD];" /> <CustomAction Id="CustomAction2" BinaryKey="BinaryId1" Execute="deferred" DllEntry="CustomAction2" Return="check" HideTarget="no"/> <InstallUISequence> <Custom Action="CustomAction1" After="AppSearch">1</Custom> <Custom Action="PrepCustomAction" Before="CustomAction2" /> <Custom Action="CustomAction2" Before="InstallFinalize" /> </InstallUISequence>
CustomAction.cpp代码
MsiGetProperty(hInstall, TEXT("PROPERTY1;PROPERTY2;PROPERTY3;PROPERTY4;"), buf, &buflen);
我预期buf会包含对应的属性值,但实际为空,请问哪里操作出错了?
问题排查与修正方案
核心错误点
延迟执行CA的属性获取方式错误
标记为Execute="deferred"的自定义动作运行在独立的系统上下文,无法直接访问普通的MSI属性,只能通过CustomActionData这个特殊属性获取预先传递的参数。你的PrepCustomAction已经把参数打包到CustomAction2的CustomActionData中,但代码里没有正确读取这个属性。MsiGetProperty调用方式错误
MsiGetProperty一次只能传入单个属性名,你传入分号拼接的多个属性名是无效用法,自然无法获取到值。
修正步骤
修改CustomAction.cpp代码,正确读取参数
先读取CustomActionData拿到完整的参数字符串,也可以直接读取其中的单个属性(MSI会自动将CustomActionData中的键值对注册为临时属性):// 方式1:读取完整的CustomActionData字符串后自行拆分 TCHAR customActionData[1024] = {0}; DWORD dataLen = sizeof(customActionData) / sizeof(TCHAR); MsiGetProperty(hInstall, TEXT("CustomActionData"), customActionData, &dataLen); // 方式2:直接读取单个属性值 TCHAR prop1Value[256] = {0}; DWORD prop1Len = sizeof(prop1Value) / sizeof(TCHAR); MsiGetProperty(hInstall, TEXT("PROPERTY1"), prop1Value, &prop1Len); // 同理读取PROPERTY2、PROPERTY3、PROPERTY4调整序列配置(建议)
延迟自定义动作通常建议放在InstallExecuteSequence中,因为InstallUISequence在静默安装场景下可能不会执行,调整后配置如下:<InstallExecuteSequence> <Custom Action="CustomAction1" After="AppSearch">1</Custom> <Custom Action="PrepCustomAction" Before="CustomAction2" /> <Custom Action="CustomAction2" Before="InstallFinalize" /> </InstallExecuteSequence>验证前置属性有效性
确保CustomAction1已经正确设置了NAME、TRUST、LOGIN、PASSWORD这些大写的公共属性(MSI中只有大写属性能跨序列传递),且属性值不为空。
内容的提问来源于stack exchange,提问作者Alexandr

