WiX Toolset 自定义操作(Custom Action)编写实战:从 Fragment 拆分到编译链接与安装序列调度 开发工具构建工具【免费下载链接】wix3WiX Toolset v3.x项目地址https://gitcode.com/gh_mirrors/wi/wix3点击查看免费下载导读本文以 WiX Toolset v3.x 官方文档中「Adding a Custom Action」一文为骨架完整讲解如何编写一个二进制DLL自定义操作从独立的ca.wxsFragment 文件定义CustomAction与Binary到在Product源码中通过InstallExecuteSequence调度该操作最后用candle/light/msiexec三步完成编译、链接与安装验证。读完本文你将掌握 WiX 自定义操作的标准编写流程、CustomAction元素的完整属性语义以及如何复用其他模块中已验证的真实示例。本文正文对应文档位于 src/chm/documents/wixdev/extensions/authoring_custom_actions.html.md其前置教程 创建 Skeleton WiX 扩展 说明了如何制作一个最小可用扩展 DLL。前置准备示例 DLL 与扩展骨架在开始编写 WiX 源码之前需要准备好两样东西一个带导出入口点的 DLL文档中假设你已经有一个名为foo.dll的示例库它导出一个入口函数FooEntryPoint。这是二进制自定义操作DLL 自定义操作的宿主——安装过程中 Windows Installer 会加载该 DLL 并调用对应入口点。一个可用的 WiX 扩展骨架文档明确假定你已经阅读过 Creating a Skeleton WiX Extension 主题。所谓骨架就是创建一个继承自Microsoft.Tools.WindowsInstallerXml.WixExtension的类并在AssemblyInfo.cs中通过AssemblyDefaultWixExtension特性标注默认扩展类随后即可用candle.exe Product.wxs -ext SampleWixExtension.dll与light.exe Product.wxs -ext SampleWixExtension.dll将扩展挂载到编译与链接工具链上。说明本文聚焦于「在 WiX 源码中编写并调度自定义操作」这是编写扩展 DLL 之后的源码侧工作。若你尚未完成 DLL 与扩展骨架请先阅读上述前置主题。Step 1创建 Fragment把自定义操作拆分为独立模块为什么单独建一个 ca.wxs直接把CustomAction定义写进包含Product的源文件中虽然可以工作但自定义操作将无法被其他产品、模块或补丁复用。文档建议遵循模块化原则新建一个独立的ca.wxs源文件来承载自定义操作定义?xml version1.0? Wix xmlnshttp://schemas.microsoft.com/wix/2006/wi Fragment CustomAction IdFooAction BinaryKeyFooBinary DllEntryFooEntryPoint Executeimmediate Returncheck/ Binary IdFooBinary SourceFilefoo.dll/ /Fragment /Wix这段代码的关键点CustomAction IdFooAction声明一个名为FooAction的自定义操作BinaryKeyFooBinary指明该操作使用FooBinary引用的二进制文件DllEntryFooEntryPoint指定 DLL 的入口函数名对应foo.dll中导出的FooEntryPointExecuteimmediate声明该操作为立即执行详见下文属性详解Returncheck声明操作返回码处理策略详见下文属性详解Binary IdFooBinary SourceFilefoo.dll/把磁盘上的foo.dll登记为安装包二进制资源供上面的自定义操作引用。这段源码「可以编译但无法链接」。原因在于链接light阶段要求整个源文件集合中至少存在一个入口 section即Product/或Module/单独一个Fragment/不是入口 section。这正是 Step 2 要把ca.wxs与产品源文件一起链接的原因。源码印证编译器如何解析 CustomAction 与 BinaryWiX v3.x 的编译器在 src/tools/wix/Compiler.cs 的ParseCustomActionElement中处理CustomAction元素。值得注意的底层行为互斥性校验BinaryKey、Directory、FileKey、Property、Script这五个「源」属性互相排斥DllEntry、Error、ExeCommand、JScriptCall、Script、Value、VBScriptCall这七个「目标」属性也互相排斥。若同时指定多个编译器会抛出CustomActionMultipleSources/CustomActionMultipleTargets错误。自动引用创建指定BinaryKey时编译器会通过CreateWixSimpleReferenceRow自动为对应的Binary表建立引用指定FileKey时自动引用File表指定Directory时自动引用Directory表。这解释了为什么ca.wxs中BinaryKey与Binary可以互相解析。类型位映射DllEntry会设置MsidbCustomActionTypeDll位Execute与Return会映射到 Windows Installer 自定义操作类型位的组合详见下文。Schema 定义CustomAction元素在 src/tools/wix/Xsd/wix.xsd 中有完整的 XML Schema 定义xse:msiRef tableCustomAction指明它对应 MSI 的CustomAction表。Step 2在 Product 中引用并调度自定义操作ca.wxs必须与一个包含Product/或Module/的源文件一起链接才能成功完成构建。文档给出的完整产品源文件如下?xml version1.0? Wix xmlnshttp://schemas.microsoft.com/wix/2006/wi Product IdPUT-GUID-HERE NameTest Package Language1033 Version1.0.0.0 Manufacturer.NET Foundation Package DescriptionMy first Windows Installer package CommentsThis is my first attempt at creating a Windows Installer database Manufacturer.NET Foundation InstallerVersion200 Compressedyes / Media Id1 Cabinetproduct.cab EmbedCabyes / Directory IdTARGETDIR NameSourceDir Directory IdProgramFilesFolder NamePFiles Directory IdMyDir NameTest Program Component IdMyComponent GuidPUT-GUID-HERE File Idreadme Namereadme.txt DiskId1 Sourcereadme.txt / /Component Merge IdMyModule Language1033 SourceFilemodule.msm DiskId1 / /Directory /Directory /Directory Feature IdMyFeature TitleMy 1st Feature Level1 ComponentRef IdMyComponent / MergeRef IdMyModule / /Feature InstallExecuteSequence Custom ActionFooAction AfterInstallFiles/ /InstallExecuteSequence /Product /Wix相比普通产品定义真正「调度」自定义操作的只有三行InstallExecuteSequence Custom ActionFooAction AfterInstallFiles/ /InstallExecuteSequence语义如下InstallExecuteSequence声明这是安装执行序列install execute sequenceCustom ActionFooAction在序列中引用在ca.wxs中定义的FooActionAfterInstallFiles把该操作排在标准动作InstallFiles之后执行。安装时FooAction的效果会在InstallFiles动作之后出现。源码印证序列元素的调度解析编译器在 src/tools/wix/Compiler.cs 的ParseSequenceElement中统一解析InstallExecuteSequence、InstallUISequence、AdvertiseExecuteSequence等序列元素当子元素名为Custom时customAction标志为trueAction属性只有自定义操作才允许出现取到动作名后通过CreateWixSimpleReferenceRow(..., CustomAction, actionName)自动为CustomAction表建立引用——这就是FooAction能被跨文件解析的原因After/Before属性用于确定动作次序并会为WixAction表建立排序引用。仓库中的真实测试数据也印证了这种写法例如 test/data/Integration/BuildingPackages/Sequencing/SequencingTests/SimpleSequencing/product.wxs 同时使用AfterInstallFiles与BeforeInstallFinalize调度同一个自定义操作。编译、链接与安装candle → light → msiexec由于现在有两个源文件需要一起处理命令行比单文件略复杂。文档给出的完整三步流程C:\test candle product.wxs ca.wxs C:\test light product.wixobj ca.wixobj –out product.msi C:\test msiexec /i product.msicandle product.wxs ca.wxs把两个源文件分别编译为对应的.wixobjWiX 对象文件。ca.wxs编译通过但尚未链接light product.wixobj ca.wixobj –out product.msi把两个对象文件链接成一个product.msi。此时FooAction与FooBinary的引用关系被解析foo.dll被打包进 MSI结合Compressedyes与EmbedCabyes二进制数据会内嵌进安装包msiexec /i product.msi运行安装。安装过程中FooAction会在InstallFiles动作之后执行其逻辑。注意light的参数–out在文档原样中是长横线实际命令行中请使用标准的短横线-out或/out。源码印证candle 与 light 的入口两个工具的实现分别在 src/tools/candle/candle.cs 与 src/tools/light/light.cs。candle的核心编译逻辑位于 src/tools/wix/Compiler.cslight的链接与绑定逻辑位于 src/tools/wix/Binder.cs 与 src/tools/wix/BinderCore.cs。若在命令行中传入了-ext扩展 DLLCompilerCore会调用扩展中的编译器扩展与绑定器扩展来支持额外元素。CustomAction 元素属性详解结合源码以下表格综合 wix.xsd 的 Schema 定义与ParseCustomActionElement的解析逻辑是编写自定义操作时的完整参考源Source属性——四选一互斥属性含义对应的 MSI 类型位源码位置BinaryKey引用Binary表中的二进制文件如 DLL、EXEMsidbCustomActionTypeBinaryDataCompiler.csFileKey引用一个随产品安装的File作为操作源MsidbCustomActionTypeSourceFileCompiler.csDirectory引用一个目录作为操作源MsidbCustomActionTypeDirectoryCompiler.csProperty引用一个安装属性作为操作源MsidbCustomActionTypePropertyCompiler.csScript特殊与内联脚本配合把脚本主体放在元素内文inner textMsidbCustomActionTypeDirectory组合Compiler.cs目标Target属性——七选一互斥属性含义对应的 MSI 类型位DllEntryDLL 自定义操作的入口函数名本文示例FooEntryPointMsidbCustomActionTypeDllExeCommandEXE 自定义操作要执行的命令行可为空字符串合法场景之一MsidbCustomActionTypeExeValue属性设置类操作的赋值文本可为空字符串MsidbCustomActionTypeTextDataError显示格式化错误字符串或错误号MsidbCustomActionTypeTextData \| MsidbCustomActionTypeSourceFileJScriptCall/VBScriptCall调用二进制内 JScript / VBScript 函数MsidbCustomActionTypeJScript/MsidbCustomActionTypeVBScriptScript内联脚本jscript / vbscript脚本体写在元素内文见上行为控制属性属性可选值语义MSI 类型位映射Executeimmediate、deferred、commit、rollback、firstSequence、secondSequence、oncePerProcess立即执行不设位deferred设置InScriptcommit设置InScript \| Commitrollback设置InScript \| RollbackfirstSequence设置FirstSequencesecondSequence设置ClientRepeatoncePerProcess设置OncePerProcessReturncheck、ignore、asyncWait、asyncNoWaitcheck不设位ignore设置ContinueasyncWait设置AsyncasyncNoWait设置Async \| ContinueImpersonateyes/nono时设置NoImpersonate即以系统账户而非当前用户身份运行TerminalServerAwareyes/noyes设置TSAware且仅对 deferred 类操作合法源码会校验 InScript 位Win64yes/noyes设置64BitScript仅对脚本类操作合法HideTargetyes/noyes设置HideTarget用于隐藏目标参数PatchUninstallyes/noyes设置PatchUninstall扩展位用于补丁卸载场景SuppressModularizationyes/noyes时编译器额外写入WixSuppressModularization表编译器的关键合法性校验在 ParseCustomActionElement 的收尾阶段编译器会做一系列交叉校验编写时务必规避非脚本自定义操作不得包含内文inner text否则报CustomActionIllegalInnerTextValue属性必须与Directory或Property搭配使用否则报IllegalAttributeWithoutOtherAttributesExeCommand必须搭配一个源属性BinaryKey/Directory/FileKey/Property非内联的VBScriptCall/JScriptCall必须搭配源属性且不能与Directory组合Win64只对脚本类操作Script、VBScriptCall、JScriptCall合法asyncNoWait只对ExeCommand类操作合法TerminalServerAware要求操作必须为 deferred 类InScript 位已设置属性设置型自定义操作PropertyValue不能用于 deferredin-script场景因为 MSI 不支持在脚本内设置属性至少指定一个目标属性否则报ExpectedAttributes。扩展真实仓库中的自定义操作示例仓库测试数据中包含多类自定义操作的真实用法可作为编写时的参考样板DLL 入口型与本文同型test/data/Extensions/UtilExtension/CAQuietExecTests/product.wxs 中QtExecImmediate使用BinaryKeyWixCA DllEntryCAQuietExec Executeimmediate ReturncheckQtExecDeferred使用Executedeferred Impersonateno并在InstallExecuteSequence中以AfterInstallFiles调度且用 CDATA 段附加了NOT REMOVE条件EXE 命令行型test/data/Integration/BuildingPackages/SmokeTests/Scenario02/customactions.wxs 展示了BinaryKeyExeCommandExecuteimmediateReturnignore的完整 Fragment 写法模块Module中的自定义操作test/data/Integration/BuildingPackages/CustomActions/CustomActionTests/SimpleCustomAction/product.wxs 以及 SequencingTests/SimpleSequencing/product.wxs 展示了在Product中直接定义CustomActionBinary并通过InstallExecuteSequence、AdminExecuteSequence调度的最小化写法多序列调度SimpleSequencing 示例同时把同一个操作放入InstallExecuteSequenceAfterInstallFiles与AdminExecuteSequenceBeforeInstallFinalize展示了自定义操作可被多个序列引用的能力。这些用例同时也在 test/src/WixTests 的集成测试体系中被编译、链接与验证说明上述属性组合是经过构建管线实际检验的。结语与延伸阅读至此一个完整可用的二进制自定义操作已经编写完成ca.wxs负责模块化定义CustomActionBinary产品源文件通过InstallExecuteSequence中的三行Custom元素完成调度candle编译、light链接、msiexec /i触发执行安装完成后在InstallFiles动作之后即可看到FooAction的执行效果。如果想进一步深入可继续阅读同目录下的系列文档Creating a Skeleton WiX Extension如何构建扩展 DLL与 Creating a Preprocessor Extension如何编写预处理器扩展也可以直接阅读编译器源码 Compiler.cs 中ParseCustomActionElement与ParseSequenceElement的完整实现以掌握每个属性最底层的位运算映射。赞分享开发工具构建工具【免费下载链接】wix3WiX Toolset v3.x项目地址https://gitcode.com/gh_mirrors/wi/wix3点击查看免费下载相关推荐WiX Toolset 标准自定义操作Standard Custom Actions完全指南从 WixUtilExtension 到各功能扩展的实战用法WiX Toolset 标准自定义操作Standard Custom Actions完全指南从 WixUtilExtension 到各功能扩展的实战用法开发工具构建工具WiX Toolset WixShellExec 自定义操作实战用 ShellExecute 在安装完成后启动文档与 URLWiX Toolset WixShellExec 自定义操作实战用 ShellExecute 在安装完成后启动文档与 URL 本指南聚焦 WiX Toolse开发工具构建工具为 Thumbor 编写自定义图片加载器Custom Image Loaders接口约定、调用链与实战实现为 Thumbor 编写自定义图片加载器Custom Image Loaders接口约定、调用链与实战实现 thumbor 内置的 HTTP 加载器 ht后端图像处理计算机视觉上一篇LeeGo架构设计深度解析为什么Brick是纯值类型的最佳选择下一篇Django-nested-admin安全指南防止嵌套表单数据注入的最佳实践创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考