ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

WiX Toolset Burn 引导程序应用接口(IBootstrapperApplication / IBootstrapperEngine)权威指南

WiX Toolset Burn 引导程序应用接口(IBootstrapperApplication / IBootstrapperEngine)权威指南 开发工具构建工具【免费下载链接】wix3WiX Toolset v3.x项目地址https://gitcode.com/gh_mirrors/wi/wix3点击查看免费下载Burn 是 WiX Toolset v3.x 中负责下载、缓存与链式安装多个安装包的引导引擎bootstrapper/chainer它以可执行程序的形式承载一个被称为引导程序应用Bootstrapper Application简称 BA的 DLL。本文基于仓库文档 bootstrapper_application_interface.html.md 与 Building a Custom Bootstrapper Application系统讲解引擎与 BA 之间通过IBootstrapperApplication引擎回调 BA与IBootstrapperEngineBA 指挥引擎两个 COM 接口建立的双向协作模型完整覆盖从OnStartup启动、Detect检测、Plan计划、Apply应用到Shutdown/OnShutdown收尾的完整生命周期并结合仓库源码IBootstrapperApplication.h、IBootstrapperEngine.h、engine.cpp 等揭示底层消息机制与 DLL 加载细节。读完本文你将能够理解自定义 BA 的接口契约、回调时序与返回值语义并掌握在 Bundle 中装配标准或自定义 BA 的完整方法。一、协作模型引擎与引导程序应用的两个方向在 WiX 的 Burn 架构中职责被清晰地切分为两半Burn 引擎engine一个原生可执行程序负责解析 Bundle 清单、缓存负载payload、执行 MSI/MSP/EXE 等包的安装与卸载并维护日志与回滚状态。仓库中引擎实现位于 src/burn/engine。引导程序应用BA一个 DLL负责面向最终用户的一切交互——显示 UI、收集安装位置与功能选择、决定何时下载/安装/修复/卸载以及把用户的决定翻译成对引擎的指令。两者之间通过两个 COM 接口通信接口方向定义位置说明IBootstrapperApplication引擎 → BA回调IBootstrapperApplication.hIID53C31D56-49C0-426B-AB06-099D717C67FE引擎主动向 BA 报告检测、计划、应用各阶段的事件与进度BA 通过返回值影响引擎行为IBootstrapperEngineBA → 引擎命令IBootstrapperEngine.hIID6480D616-27A0-44D7-905B-81512C29C2FBBA 向引擎下达Detect、Plan、Apply、Quit等命令并读写变量、格式化字符串正如文档所述The engine communicates with the bootstrapper application through callbacks to the IBootstrapperApplication interface——引擎发给 BA 的第一条消息就是IBootstrapperApplication::OnStartup()。二、起点OnStartup 与引擎的消息循环引擎加载 BA 后发起的第一个回调是OnStartup// IBootstrapperApplication::OnStartup STDMETHOD(OnStartup)() 0;典型的 BA 会在这个回调中启动一个新线程并显示用户界面然后立即返回。文档特别强调After the BA returns from OnStartup, the engine enters its idle loop and waits for commands from the BA via IBootstrapperEngine.——即 BA 从OnStartup返回后引擎就进入空闲循环idle loop不再主动推进任何安装逻辑接下来的一切都由 BA 通过IBootstrapperEngine发命令驱动。从源码结构看这一流程在 engine.cpp 中对应引擎的主运行函数先通过EngineForApplicationCreate创建供 BA 使用的引擎接口对象再调用UserExperienceLoad加载 BA DLL 并取得其实例随后调用OnStartup源码第 711 行pEngineState-userExperience.pUserExperience-OnStartup()紧接着进入一个标准的 Windows 消息泵while (0 ! (fRet ::GetMessageW(msg, NULL, 0, 0))) { if (-1 fRet) { ... } else { ProcessMessage(pEngineState, msg); } }这个细节解释了 Burn 的一条核心设计原则引擎与 BA 之间的所有命令都是异步投递的。BA 调用IBootstrapperEngine的方法并不会同步执行安装逻辑而是把对应的窗口消息如WM_BURN_DETECT、WM_BURN_PLAN、WM_BURN_APPLY、WM_BURN_QUIT投递到引擎线程的消息队列由引擎的消息泵逐个处理。实现证据见 EngineForApplication.cpp 与 engine.cpp 中的ProcessMessage分发逻辑。三、检测阶段IBootstrapperEngine::DetectBA 启动后的第一件事应该是检测——即让引擎扫描目标机器判断链中各包当前的安装状态。BA 通过调用IBootstrapperEngine::Detect发起// IBootstrapperEngine::Detect STDMETHOD(Detect)() 0;在当前的仓库源码中Detect还带有一个可选的父窗口句柄参数见 IBootstrapperEngine.hSTDMETHOD(Detect)( __in_opt HWND hwndParent NULL ) 0;调用后引擎异步执行检测并通过IBootstrapperApplication回调把过程与结果汇报给 BA。与检测相关的回调在头文件中有完整的定义主要包括OnDetectBegin(fInstalled, cPackages)检测开始fInstalled表示 Bundle 当前是否已安装cPackages为待检测包数量OnDetectForwardCompatibleBundle检测到前向兼容的 Bundle可用于替换OnDetectUpdateBegin/OnDetectUpdate/OnDetectUpdateCompleteBundle 自更新候选的检测OnDetectRelatedBundle检测到相关 Bundle升级、补丁、依赖等关系OnDetectPackageBegin/OnDetectCompatiblePackage/OnDetectRelatedMsiPackage/OnDetectTargetMsiPackage/OnDetectMsiFeature针对单个包的检测细节OnDetectPackageComplete(wzPackageId, hrStatus, state)/OnDetectComplete(hrStatus)单个包与整个检测阶段的结束信号state为BOOTSTRAPPER_PACKAGE_STATE枚举UNKNOWN/ABSENT/CACHED/PRESENT/SUPERSEDED等。值得注意的返回值约定同样适用于后文大部分回调回调返回IDCANCEL可中止当前阶段返回IDNOACTION则继续。这两个常量及IDDOWNLOAD(101)、IDRESTART(102)、IDSUSPEND(103)、IDRELOAD_BOOTSTRAPPER(104) 都在 IBootstrapperEngine.h 中定义IDERROR为 -1IDNOACTION为 0。四、计划阶段IBootstrapperEngine::Plan 与 BOOTSTRAPPER_ACTION检测完成后BA 需要确定用户想要执行的总体操作。文档指出Historically this happens as a wizard sequence, prompting the user for installation location, feature selection, etc.——典型的 BA 会以向导wizard形式逐步询问安装位置、功能选择等待所有决定就绪后调用Plan让引擎制定执行计划// IBootstrapperEngine::Plan STDMETHOD(Plan)( __in BOOTSTRAPPER_ACTION action ) 0;BOOTSTRAPPER_ACTION是一个枚举用于指定总体动作。文档强调最常用的动作是install安装、uninstall卸载和 repair修复。当前仓库头文件中的完整枚举顺序敏感源码注释明确指出枚举值的排列顺序不可随意改动因为部分代码路径依赖/比较枚举值含义BOOTSTRAPPER_ACTION_UNKNOWN未知动作BOOTSTRAPPER_ACTION_HELP显示帮助BOOTSTRAPPER_ACTION_LAYOUT仅布局下载/缓存负载而不安装BOOTSTRAPPER_ACTION_UNINSTALL卸载BOOTSTRAPPER_ACTION_CACHE仅缓存BOOTSTRAPPER_ACTION_INSTALL安装BOOTSTRAPPER_ACTION_MODIFY修改BOOTSTRAPPER_ACTION_REPAIR修复BOOTSTRAPPER_ACTION_UPDATE_REPLACE以更新包替换当前 BundleBOOTSTRAPPER_ACTION_UPDATE_REPLACE_EMBEDDED以内嵌更新包替换当前 Bundle计划阶段的回调包括OnPlanBegin(cPackages)、OnPlanRelatedBundle、OnPlanPackageBegin(wzPackageId, pRequestedState)、OnPlanCompatiblePackage、OnPlanTargetMsiPackage、OnPlanMsiFeature以及结束信号OnPlanPackageComplete和OnPlanComplete(hrStatus)。注意多个Plan回调都带有__inout BOOTSTRAPPER_REQUEST_STATE* pRequestedState参数——BA 不仅被动接收计划状态还可以就地改写请求状态FORCE_ABSENT/ABSENT/CACHE/PRESENT/REPAIR从而影响该包最终是安装、卸载、仅缓存还是修复这是实现复杂交互逻辑的关键挂点。五、应用阶段IBootstrapperEngine::Apply计划完成之后BA 调用Apply让引擎真正执行变更// IBootstrapperEngine::Apply STDMETHOD(Apply)( __in_opt HWND hwndParent ) 0;文档特别强调了hwndParent的作用BA 应提供一个窗口句柄以确保需要提权elevation时出现的 UAC 提示能够处于活动状态并显示在其他窗口之上。若 BA 是被动式passive或嵌入式场景可传入NULL。仓库中Apply同样以WM_BURN_APPLY消息异步投递见 EngineForApplication.cpp。文档还指出The bulk of the BA time will be spent handling callbacks from the Apply action.——BA 的绝大部分运行时间都花在处理 Apply 阶段的各种回调上。Apply 是一个多阶段的流水线IBootstrapperApplication头文件中按顺序定义了完整的回调集可归纳为开始/结束OnApplyBegin、OnApplyPhaseCount(dwPhaseCount)v3 中紧随OnApplyBegin之后告知 BA 阶段总数、OnApplyComplete(hrStatus, restart)提权OnElevate每次引擎执行仅触发一次返回IDCANCEL可中止提权并停止应用进度OnProgress(dwProgressPercentage, dwOverallPercentage)错误OnError(errorType, wzPackageId, dwCode, wzError, uiFlags, cData, rgwzData, nRecommendation)errorType为BOOTSTRAPPER_ERROR_TYPEELEVATE/WINDOWS_INSTALLER/EXE_PACKAGE/HTTP_AUTH_SERVER/HTTP_AUTH_PROXY/APPLY返回IDNOACTION会让引擎走默认错误处理通常导致 Apply 失败注册OnRegisterBegin/OnRegisterComplete(hrStatus)以及卸载路径上的OnUnregisterBegin/OnUnregisterComplete缓存CacheOnCacheBegin、OnCachePackageBegin、OnCacheAcquireBegin/Progress/Complete、OnCacheVerifyBegin/Complete、OnCachePackageComplete、OnCacheComplete其中OnResolveSource用于本地找不到负载时决定重试本地源IDRETRY还是改用下载源IDDOWNLOADBA 可在返回前调用IBootstrapperEngine::SetLocalSource/SetDownloadSource更换来源执行ExecuteOnExecuteBegin、OnExecutePackageBegin(wzPackageId, fExecute)、OnExecutePatchTarget、OnExecuteProgress、OnExecuteMsiMessage、OnExecuteFilesInUse、OnExecutePackageComplete、OnExecuteComplete预批准程序OnLaunchApprovedExeBegin/OnLaunchApprovedExeComplete(hrStatus, dwProcessId)。OnExecutePackageComplete的返回值值得单独说明因为它是实现安装后重启的关键IDRESTART指示引擎停止处理链并重启机器引擎在重启后会再次启动继续IDSUSPEND指示引擎挂起当前状态可用于配合后续恢复IDIGNORE/IDRETRY则分别表示忽略非关键包的失败或重试该包。对应地OnApplyComplete返回IDRESTART也可请求整体重启若已由OnExecutePackageComplete发起过重启则被忽略。六、收尾通知引擎退出与 OnShutdown当 BA 完成所有工作或用户取消/出错时它应通知引擎退出。文档中给出的调用是// IBootstrapperEngine::Shutdown STDMETHOD(Shutdown)( __in DWORD dwExitCode, __in BOOL fRestart ) 0;需要提醒的是当前仓库的实际头文件 IBootstrapperEngine.h 中这一方法名为Quit且只接受退出码STDMETHOD(Quit)( __in DWORD dwExitCode ) 0;从源码结构看Quit通过PostThreadMessageW(m_dwThreadId, WM_BURN_QUIT, dwExitCode, 0)投递消息引擎消息泵收到WM_BURN_QUIT后调用CoreQuit并退出消息循环见 engine.cpp。文档中的fRestart参数是否需要重启在 v3 源码中实际上由OnShutdown的返回值承担。因此编写 BA 时应以当前仓库头文件签名为准文档所述属于较早版本的接口形态。BA 发起退出后引擎会最后一次回调 BA 的OnShutdown// IBootstrapperApplication::OnShutdown STDMETHOD_(void, OnShutdown)() 0;同样地当前仓库头文件 IBootstrapperApplication.h 中OnShutdown已升级为返回int的形态可借此向引擎传达特殊指令返回IDRESTART指示引擎重启机器引擎在重启后不再自动重新启动若OnExecutePackageComplete已发起过重启则忽略返回IDRELOAD_BOOTSTRAPPER指示引擎卸载 BA 并重新加载引擎、再次加载 BA典型用途是从原生 BA 切换到托管managedBA返回其他值一律忽略。引擎退出路径的处理位于 engine.cpp退出消息循环后调用OnShutdown根据返回值设置fRestart或pfReloadApp随后卸载 UXUserExperienceUnload并释放引擎接口对象。七、引擎如何装载 BA导出函数与 BOOTSTRAPPER_COMMANDBA 之所以是一个 DLL是因为引擎通过标准的 DLL 加载机制与其对接。加载流程实现在 userexperience.cpp 的UserExperienceLoad中先LoadLibraryExW加载 BA DLL以LOAD_WITH_ALTERED_SEARCH_PATH方式保证能找到随附的资源 payload再用GetProcAddress查找导出函数BootstrapperApplicationCreate最后调用它创建 BA 实例。该导出函数的签名与 ba/index.html.md 一致extern C HRESULT WINAPI BootstrapperApplicationCreate( __in IBootstrapperEngine* pEngine, __in const BOOTSTRAPPER_COMMAND* pCommand, __out IBootstrapperApplication** ppApplication )pEngine引擎提供的IBootstrapperEngine接口指针BA 保存它即可在后续任意时刻向引擎发命令pCommand指向BOOTSTRAPPER_COMMAND结构内含从命令行解析出的信息。该结构在 IBootstrapperApplication.h 中定义字段包括action期望动作、displayBOOTSTRAPPER_DISPLAYEMBEDDED/NONE/PASSIVE/FULL、restartBOOTSTRAPPER_RESTARTNEVER/PROMPT/AUTOMATIC/ALWAYS、wzCommandLine、nCmdShow、resumeTypeBOOTSTRAPPER_RESUME_TYPE如REBOOT、INTERRUPTED、ARP等用于实现断点恢复、hwndSplashScreen、relationType、fPassthrough、wzLayoutDirectoryppApplication成功时返回 BA 的IBootstrapperApplication实现。BA 还可可选地导出BootstrapperApplicationDestroy引擎会在卸载 DLL 之前调用它extern C void WINAPI BootstrapperApplicationDestroy()文档指出绝大多数清理工作应在IBootstrapperApplication::OnShutdown中完成BootstrapperApplicationDestroy只用于清理那些在BootstrapperApplicationCreate期间创建、需要与 BA 实例同生共死的资源。引擎侧在UserExperienceUnload中通过GetProcAddress(BootstrapperApplicationDestroy)探测并调用该导出见 userexperience.cpp随后FreeLibrary。兼容性警示引自 ba/index.html.md升级 WiX Toolset 的 minor 版本时必须重新编译 BA——minor 版本只保证源代码级兼容不保证二进制兼容。这是自定义 BA 开发者需要长期遵守的发布纪律。八、命令投递的底层机制线程消息把前面各节串起来看Burn 的异步协作机制可以归纳为一条完整的调用链BA 调用IBootstrapperEngine::Detect/Plan/Apply/Quit引擎接口实现EngineForApplication.cpp把这些调用转换为PostThreadMessageW投递的WM_BURN_DETECT/WM_BURN_PLAN/WM_BURN_APPLY/WM_BURN_QUIT消息引擎线程的消息泵engine.cpp 的ProcessMessage取出消息分发到CoreDetect/CorePlan/CoreApply/CoreQuit等核心函数核心函数执行期间通过IBootstrapperApplication回调把阶段事件、进度和错误反馈给 BA。因此BA 中所有引擎调用都会立即返回只保证投递成功真正的安装动作发生在引擎线程上。这也是为什么 BA 的 UI 线程可以保持响应、进度条可以平滑更新——UI 渲染与安装执行天然解耦。如果 BA 需要在引擎繁忙时保护状态可参考引擎侧提供的UserExperienceActivateEngine/UserExperienceDeactivateEngine/UserExperienceEnsureEngineInactive等同步辅助函数见 userexperience.cpp它们通过临界区保证同一时刻只有一个方向在操作引擎。九、在 Bundle 中装配 BABootstrapperApplication 与 WixStandardBootstrapperApplication理解接口之后回到 WiX 语言层面。文档 authoring_bundle_application.html.md 说明每个 Bundle 都需要一个 BA 来驱动 Burn 引擎。BootstrapperApplication元素用于定义一个全新的 BABootstrapperApplicationRef元素用于引用已存在于某个Fragment或 WiX 扩展中的 BA。绝大多数场景无需编写自定义 BA因为 WiX 提供了标准 BAWiX Standard Bootstrapper Application位于 WixBalExtension.dll。在 Bundle 中引用它?xml version1.0? Wix xmlnshttp://schemas.microsoft.com/wix/2006/wi Bundle BootstrapperApplicationRef IdWixStandardBootstrapperApplication.RtfLicense / Chain /Chain /Bundle /Wix标准 BA 提供多个变体详见 wixstdba/index.html.mdWixStandardBootstrapperApplication.RtfLicense——欢迎页显示 RTF 许可证类似 WixUI AdvancedWixStandardBootstrapperApplication.HyperlinkLicense——欢迎页以超链接方式提供许可证观感更现代简洁WixStandardBootstrapperApplication.HyperlinkSidebarLicense——基于 HyperlinkLicense但对话框更大、首页图片更大WixStandardBootstrapperApplication.RtfLargeLicense——类似 RtfLicense 的大对话框版本可显示版本号WixStandardBootstrapperApplication.HyperlinkLargeLicense——类似 HyperlinkLicense 的大对话框版本可显示版本号。后三种变体可通过bal:WixStandardBootstrapperApplication子元素打开ShowVersionyes在欢迎页显示 Bundle 版本?xml version1.0? Wix xmlnshttp://schemas.microsoft.com/wix/2006/wi xmlns:balhttp://schemas.microsoft.com/wix/BalExtension Bundle BootstrapperApplicationRef IdWixStandardBootstrapperApplication.RtfLicense bal:WixStandardBootstrapperApplication LicenseFilepath\to\license.rtf ShowVersionyes / /BootstrapperApplicationRef Chain /Chain /Bundle /Wix构建时须提供 WixBalExtension。若上述代码存于example.wxs则依次执行即可产出example.exeBundlecandle.exe example.wxs -ext WixBalExtension light.exe example.wixobj -ext WixBalExtension当标准 BA 无法满足需求时可开发自定义 BA DLL 并用BootstrapperApplication装配?xml version1.0? Wix xmlnshttp://schemas.microsoft.com/wix/2006/wi Bundle BootstrapperApplication SourceFilepath\to\ba.dll / Chain /Chain /Bundle /Wix自定义 BA 往往需要随附资源文件本地化资源、主题等可在BootstrapperApplication内部添加Payload子元素或通过PayloadGroupRef引用其他Fragment中定义的PayloadGroup?xml version1.0? Wix xmlnshttp://schemas.microsoft.com/wix/2006/wi Bundle BootstrapperApplication SourceFilepath\to\ba.dll Payload SourceFilepath\to\en-us\resources.dll / PayloadGroupRef IdResourceGroupforJapanese / /BootstrapperApplication Chain /Chain /Bundle /Wix注意 BA DLL 及其全部 payload 都会被引擎当作 UX 负载缓存到临时目录且第一个 payload 即 BA DLL 本身见 userexperience.cpp 中payloads.rgPayloads[0]的加载逻辑其余 payload 会被放置在同一工作目录下供LoadLibraryExW(LOAD_WITH_ALTERED_SEARCH_PATH)解析依赖。十、实战要点速查生命周期铁律OnStartup中启动 UI 线程后立即返回 → 引擎进入消息循环 → BA 用Detect开始 → 用Plan(BOOTSTRAPPER_ACTION)制定计划 → 用Apply(hwndParent)执行 → 用Quit/Shutdown(dwExitCode)退出 → 引擎最后回调OnShutdown。同步性是假象所有引擎命令均为异步投递线程消息立即返回只代表投递成功真实进度通过回调反映BA 的 UI 不应假设命令已执行完毕。回调返回值是控制手段绝大多数回调返回IDCANCEL中止、IDNOACTION继续OnResolveSource还接受IDRETRY/IDDOWNLOADOnExecutePackageComplete/OnApplyComplete接受IDRESTART/IDSUSPEND等OnShutdown接受IDRESTART/IDRELOAD_BOOTSTRAPPER。Plan类回调可改写请求状态通过修改pRequestedState就地决定包的安装/卸载/修复/缓存是自定义交互逻辑的主要扩展点。必须提供hwndParent给Apply否则提权提示可能无法正确置顶显示。导出两个函数BootstrapperApplicationCreate必选与BootstrapperApplicationDestroy可选签名以 IBootstrapperApplication.h 为准。保持二进制兼容WiX minor 版本升级需重编译 BA。不想写 C 也可用托管方案参考 ManagedBundleRunner 等示例以及仓库内置的 WixBAsrc/Setup/WixBA——后者本身就是一份完整的原生 BA 参考实现包含根视图、安装/进度/更新视图模型RootViewModel.cs、InstallationViewModel.cs 等可作为研读接口用法的活教材。若需继续深入仓库内与本文配套的文档还包括 Building Installation Package Bundles、Author the Bootstrapper Application for a Bundle、Author a Bundle Package Manifest 与 Working with WiX Standard Bootstrapper Application可沿此路径系统掌握 Bundle 构建的完整知识体系。赞分享开发工具构建工具【免费下载链接】wix3WiX Toolset v3.x项目地址https://gitcode.com/gh_mirrors/wi/wix3点击查看免费下载相关推荐WiX Toolset v3 项目教程WiX Toolset v3 项目教程 1. 项目的目录结构及介绍 WiX Toolset v3 项目的目录结构如下 wix3/ ├── CONTRIBUTI开发工具构建工具【亲测免费】 WiX Toolset v3 使用教程WiX Toolset v3 使用教程 1. 项目介绍 WiX Toolset 是一个用于构建 Windows 安装包的开源工具集。它允许开发者通过 XML 源开发工具构建工具WiX Toolset v3: 打造专业Windows安装程序的利器WiX Toolset v3: 打造专业Windows安装程序的利器 WiX Toolset v3一个专为Windows安装包构建而生的开源工具集采用XML开发工具构建工具上一篇res-downloader5 分钟把视频号、抖音、小红书资源抓下来的下载工具下一篇Llama Stack Apps状态管理全局存储与组件通信创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表