
开发工具构建工具【免费下载链接】wix3WiX Toolset v3.x项目地址https://gitcode.com/gh_mirrors/wi/wix3点击查看免费下载本指南聚焦 WiX Toolset v3.x 中由 WixUtilExtension 提供的WixShellExec标准自定义操作讲解它如何借助 Windows Shell 的ShellExecute打开文档、可执行文件与 URL 目标并给出从安装完成后启动已安装应用到调用默认关联程序打开 readme的完整可运行方案。读完本文你将掌握WixShellExecTarget属性的设置规则、CustomAction的声明方式、触发时机控制以及该操作在源码层面的真实执行流程与错误处理机制。什么是 WixShellExecWixShellExec是 WiX Toolset 提供的标准自定义操作Standard Custom Action其实现代码位于wixca原生 DLL 中随WixUtilExtension一起分发。它的作用是通过 Windows Shell 打开文档或 URL 目标——即不直接以 CreateProcess 方式拉起进程而是把目标交给系统由系统根据扩展名或协议关联的默认应用程序来处理。在 WiX 文档的 标准自定义操作索引 中ShellExecute custom action被明确归类为launch document or URL targets via the Windows shell归属于 WixUtilExtension。一个典型应用场景是安装完成后启动 readme 文件.txt、.html等或产品主页 URL让系统使用用户注册的默认应用记事本、浏览器等打开它们。工作原理从属性到 ShellExecute 的调用链WixShellExec的执行逻辑非常直接在源码 shellexecca.cpp 中可以完整看到读取属性WixShellExec入口函数通过WcaGetFormattedProperty(LWixShellExecTarget, pwzTarget)读取WixShellExecTarget属性。关键点是WcaGetFormattedProperty—— 它会对属性值执行Windows Installer 格式化Format因此属性中写[#fileId]、[INSTALLDIR]这类标记会在执行时被替换为真实路径。校验非空若WixShellExecTarget为空或未设置直接返回E_INVALIDARG并使安装失败对应ERROR_INSTALL_FAILURE。格式化目标源码注释与日志WcaLog(LOGMSG_VERBOSE, WixShellExecTarget is %ls, ...)确认目标值在运行时被格式化后再使用。调用 ShellExecute核心函数ShellExec执行::ShellExecuteW(NULL, NULL, wzTarget, NULL, sczWorkingDirectory, SW_SHOWDEFAULT)。其中使用默认 verb即通常的open动词以目标文件所在目录作为合理的工作目录源码中特别注明避免使用 MSI 默认的 system32 目录若该目录不存在则置空窗口以SW_SHOWDEFAULT显示。从源码结构还可以推断一个细节WixShellExec属于立即执行型操作Executeimmediate它在启动应用后不会等待应用关闭便返回这正是文档强调只能作为立即型自定义操作使用的原因——如果把它放进延迟执行deferred序列既无法获得用户会话下的正确环境也无法在时序上等待目标程序结束。为什么只能作为立即型Immediate自定义操作原文档明确说明WixShellExecute 只能用作 immediate custom action因为它启动一个应用程序且不会等待它关闭。这一点在 UtilExtension.wxs 中定义的默认实例上得到了印证Fragment PropertyRef IdWixShellExecTarget / CustomAction IdWixShellExec BinaryKeyWixCA DllEntryWixShellExec Executeimmediate Returncheck Impersonateyes / /Fragment其中Executeimmediate在安装序列中立即执行Returncheck检查返回值失败则终止安装日志中对应 failed to launch targetImpersonateyes以安装用户身份运行确保打开的文档/URL 显示在正确的用户会话中。使用方式一直接引用默认实例 WixShellExecWixShellExec的默认实例已经由 WixUtilExtension 预置定义在上面的 Fragment 中你不需要自己写CustomAction只需两步第一步设置WixShellExecTarget属性例如用文件表 ID 引用安装目录中的目标文件Property IdWixShellExecTarget Value[#myapplication.exe] /第二步通过CustomActionRef引用它并确保它被放入安装序列的合适位置例如通过Publish事件或序列安排触发CustomActionRef IdWixShellExec /这是只需一个 ShellExec 操作时的最简用法。注意WixShellExecTarget的值会经过格式化[#fileId]会在运行时解析为文件的完整安装路径。使用方式二自定义 Id 的多实例用法源码 UtilExtension.wxs 中有一段注释值得注意!-- ShellExec custom actions (for when only one is needed; multiple executions need their own IDs) --即默认实例适用于只需要执行一次 ShellExec的场景如果需要多次执行例如同时打开文档和 URL必须自行声明多个具有不同 Id 的CustomAction每个都指向BinaryKeyWixCA、DllEntryWixShellExec并分别配合各自的目标属性或复用同一个WixShellExecTarget但设置不同的触发条件。这符合 Windows Installer 中一个自定义操作在一个安装会话中只应执行一次的惯例。完整实战安装完成后启动已安装的应用原文档给出了权威的演练入口How To: Run the Installed Application After Setup。下面完整复现并展开该教程的四个步骤与完整样例。前置把扩展库加入项目使用 WixUtilExtension自定义操作所在与 WixUIExtensionUI 所在。命令行方式在candle与light上都要加-extcandle.exe yourfile.wxs -ext WixUIExtension -ext WixUtilExtension light.exe yourfile.wixobj -ext WixUIExtension -ext WixUtilExtension -out yourfile.msiVisual Studio 中则通过Add Reference...对话框勾选WixUIExtension.dll与WixUtilExtension.dll。扩展 DLL 会被链接器自动把对应的自定义操作记录、Binary 表行与错误消息一并带入最终 MSI详见 使用标准自定义操作 中的说明使用User元素构建后可用 Orca 在 MSI 的 Error、CustomAction、Binary 表中验证。Step 1引入 Minimal UI在Product内加入UI UIRef IdWixUI_Minimal / /UIStep 2显示安装完成对话框上的可选复选框WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT属性由标准 UI 序列提供一旦设置即会在最后一个界面显示复选框并把属性值作为复选框标签文字Property IdWIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT ValueLaunch My Application Name /Step 3声明自定义操作并设置目标属性Property IdWixShellExecTarget Value[#myapplication.exe] / CustomAction IdLaunchApplication BinaryKeyWixCA DllEntryWixShellExec Impersonateyes /WixShellExecTarget使用[#myapplication.exe]#前缀指示 WiX 在运行时查找 Id 为myapplication.exe的文件的完整安装路径CustomAction的BinaryKeyWixCA与DllEntryWixShellExec指明实现所在二进制与入口点对应 wixca.def 中导出的WixShellExec符号Impersonateyes让自定义操作以安装用户身份运行。Step 4用 Publish 事件触发仅仅声明还不够必须告诉 Windows Installer 何时触发。把Publish放进UI元素内让它挂在ExitDialog的Finish按钮上UI UIRef IdWixUI_Minimal / Publish DialogExitDialog ControlFinish EventDoAction ValueLaunchApplication WIXUI_EXITDIALOGOPTIONALCHECKBOX 1 and NOT Installed /Publish /UI属性说明DialogExitDialog、ControlFinish绑定到结束对话框的 Finish 按钮EventDoAction点击按钮时运行指定自定义操作ValueLaunchApplication即 Step 3 声明的操作 Id条件WIXUI_EXITDIALOGOPTIONALCHECKBOX 1 and NOT Installed仅当复选框被勾选且本次是全新安装而非卸载/修复时才执行。完整样例把上述片段组合进一个完整的 WiX 工程含文件安装部分来自 How To 文档?xml version1.0 encodingUTF-8? Wix xmlnshttp://schemas.microsoft.com/wix/2006/wi Product Id* UpgradeCodePUT-GUID-HERE Version1.0.0.0 Language1033 NameMy Application Name ManufacturerMy Manufacturer Name Package InstallerVersion300 Compressedyes / Media Id1 Cabinetmyapplication.cab EmbedCabyes / Directory IdTARGETDIR NameSourceDir Directory IdProgramFilesFolder Directory IdAPPLICATIONROOTDIRECTORY NameMy Application Name / /Directory /Directory DirectoryRef IdAPPLICATIONROOTDIRECTORY Component Idmyapplication.exe GuidPUT-GUID-HERE File Idmyapplication.exe SourceMySourceFiles\MyApplication.exe KeyPathyes Checksumyes / /Component Component Iddocumentation.html GuidPUT-GUID-HERE File Iddocumentation.html SourceMySourceFiles\documentation.html KeyPathyes / /Component /DirectoryRef Feature IdMainApplication TitleMain Application Level1 ComponentRef Idmyapplication.exe / ComponentRef Iddocumentation.html / /Feature UI UIRef IdWixUI_Minimal / Publish DialogExitDialog ControlFinish EventDoAction ValueLaunchApplication WIXUI_EXITDIALOGOPTIONALCHECKBOX 1 and NOT Installed /Publish /UI Property IdWIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT ValueLaunch My Application Name / Property IdWixShellExecTarget Value[#myapplication.exe] / CustomAction IdLaunchApplication BinaryKeyWixCA DllEntryWixShellExec Impersonateyes / /Product /Wix打开文档与 URL配合默认关联程序的常见做法WixShellExec并不限制目标必须是可执行文件。由于底层是ShellExecuteW目标可以是文档文件.txt、.html、.chm等由注册表中关联的默认应用打开URLhttp://...、mailto:...等协议由默认浏览器/邮件客户端处理。因此最常见的用法之一是在安装完成后用系统默认程序打开随产品安装的 readme 文档例如Property IdWixShellExecTarget Value[#readme.html] / CustomActionRef IdWixShellExec /WixShellExecTarget也可以用普通路径字面量如https://www.example.com/或[INSTALLDIR]docs\readme.txt只要该值能在运行时被格式化出有效目标即可。源码级原理ShellExec 与错误处理在 shellexecca.cpp 中ShellExec的工作目录处理与错误映射是理解此操作健壮性的关键// a reasonable working directory (not the system32 default from MSI) is the directory where the target lives hr PathGetDirectory(wzTarget, sczWorkingDirectory); ... HINSTANCE hinst ::ShellExecuteW(NULL, NULL, wzTarget, NULL, sczWorkingDirectory, SW_SHOWDEFAULT); if (hinst HINSTANCE(32)) { // 将 ShellExecute 返回的错误代码映射为 HRESULT }ShellExecute返回不大于 32 的值表示失败源码将其映射为对应的 HRESULT 与ERROR_*代码常见映射包括ShellExecute 返回码含义映射结果ERROR_FILE_NOT_FOUND目标文件不存在ERROR_FILE_NOT_FOUNDERROR_PATH_NOT_FOUND路径不存在ERROR_PATH_NOT_FOUNDERROR_BAD_FORMAT格式错误ERROR_BAD_FORMATSE_ERR_ASSOCINCOMPLETE/SE_ERR_NOASSOC无关联程序ERROR_NO_ASSOCIATIONSE_ERR_DDEBUSY/SE_ERR_DDEFAIL/SE_ERR_DDETIMEOUTDDE 失败ERROR_DDE_FAILSE_ERR_DLLNOTFOUNDDLL 缺失ERROR_DLL_NOT_FOUNDSE_ERR_OOM内存不足E_OUTOFMEMORYSE_ERR_ACCESSDENIED拒绝访问E_ACCESSDENIED任何失败都会使WixShellExec以ERROR_INSTALL_FAILURE结束因为Returncheck并通过日志输出 failed to launch target 便于排查。关联变体WixShellExecBinary同一个源文件中还导出了第二个入口WixShellExecBinary同样在 wixca.def 中导出。它对应WixShellExecBinaryId属性从 MSI 的Binary 表中按 Id 读取一段二进制数据ExtractBinary查询SELECT Data FROM Binary WHERE Name...将其解压写入%TEMP%目录下的临时文件再交给同一个ShellExec执行。这个变体适合需要把内嵌资源例如一段脚本或一个小工具临时落地后通过 Shell 关联打开的场景其使用约束与WixShellExec一致immediate、check、impersonate。注意事项小结只能立即执行WixShellExec不等待目标进程退出因此只能安排为 immediate 自定义操作并放在安装流程末尾如 UI 的 Finish 事件触发属性可格式化WixShellExecTarget在运行时经过格式化可放心使用[#fileId]、[INSTALLDIR]等标记多次执行需自定义 Id默认实例WixShellExec只适合单次执行多次启动需要自行声明多个CustomAction空值即失败目标属性为空或无效时安装会以失败告终E_INVALIDARG请确保触发条件严格可控用户上下文Impersonateyes使操作以安装用户身份运行文档/URL 会在用户会话中正确打开。延伸阅读How To: Run the Installed Application After Setup —— 本文实战示例的原始出处使用标准自定义操作 —— 扩展 DLL 与 candle/light 命令行用法标准自定义操作索引 —— WixUtilExtension 下其他标准操作一览实现源码shellexecca.cpp 与 wixca.def默认实例定义UtilExtension.wxs赞分享开发工具构建工具【免费下载链接】wix3WiX Toolset v3.x项目地址https://gitcode.com/gh_mirrors/wi/wix3点击查看免费下载相关推荐从变更记录到源码实现深入解析 discordjs/brokers 的 Redis 消息代理设计与 1.0.0 破坏性重构从变更记录到源码实现深入解析 discordjs/brokers 的 Redis 消息代理设计与 1.0.0 破坏性重构 discordjs/broker开发工具构建工具Windows安装包制作神器WiX Toolset完全指南Windows安装包制作神器WiX Toolset完全指南 还在为Windows软件打包分发而烦恼吗 想要一个既专业又免费的安装包制作工具WiX To开发工具构建工具Hardhat 仓库贡献指南pnpm monorepo 下的构建、测试与提交全流程Hardhat 仓库贡献指南pnpm monorepo 下的构建、测试与提交全流程 本文是 Hardhat 开源仓库 CONTRIBUTING.md htt开发工具构建工具上一篇mio零依赖的C内存映射文件终极指南下一篇mrustc过程宏支持自定义派生和宏系统的工作原理创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考