Ruffle Windows MSI 安装包构建指南:使用 WiX 工具集为 ruffle_desktop 打包安装程序
【免费下载链接】ruffleA Flash Player emulator written in Rust项目地址: https://gitcode.com/GitHub_Trending/ru/ruffle
本指南基于 Ruffle 仓库中的 desktop/packages/windows/wix/README.md 及同目录下的 WiX 工程源码,完整讲解如何把 Ruffle 桌面版(ruffle_desktop)构建为 Windows 标准.msi安装包。你将掌握 WiX v4 工具链的安装配置、RUFFLE_VERSION等环境变量的含义与取值规则、完整构建命令及其可选参数,并深入理解 ruffle.wxs 中安装目录、文件关联、环境变量 PATH、升级策略与自定义安装向导界面的底层实现。
一、背景:为什么要为 Ruffle 桌面版制作 MSI 安装包
Ruffle 是一个用 Rust 编写的 Flash Player 模拟器,同时面向桌面与 Web(WebAssembly)。桌面版本体位于 desktop 目录,Cargo 包名为ruffle_desktop,构建产物为ruffle.exe(Windows 下OriginalFilename即ruffle.exe,见 desktop/Cargo.toml)。为了让 Windows 用户能够通过标准的“双击安装向导”完成部署、获得开始菜单/桌面快捷方式、.swf文件关联以及系统 PATH 写入等能力,仓库在desktop/packages/windows/wix目录下维护了一套基于 WiX(Windows Installer XML)工具集的 MSI 打包工程。
该目录包含 4 个文件,它们共同构成完整的 MSI 工程:
README.md:构建 MSI 的操作文档(即本文所依据的核心文档);ruffle.wxs:主安装脚本,定义包元数据、目录结构、组件、文件关联与功能树;dialog.wxi:自定义安装向导 UI 的 Include 片段;banner.png、dialog.png:安装向导使用的横幅与对话框背景位图资源。
二、前置条件:准备 WiX 工具链与 Ruffle 构建产物
在构建 MSI 之前,需要先完成环境准备。按照 README 的说明,依次执行以下步骤:
安装 WiX 工具集(v4 .NET 工具)。WiX v4 通过 .NET 全局工具分发,使用如下命令安装:
dotnet tool install --global wix添加 UI 扩展,用于生成安装向导界面:
wix extension add -g WixToolset.UI.wixext添加 Util 扩展,用于
util:PermissionEx(目录权限)等实用功能:wix extension add -g WixToolset.Util.wixext这两条命令也可以在
ruffle.wxs文件头部的注释中看到对应说明(见 ruffle.wxs),与 README 保持一致。构建 Ruffle 桌面版 release 产物。MSI 需要把已经编译好的
ruffle_desktop.exe打进安装包。README 给出的方式是先构建整个桌面项目:cargo build --release也可参考仓库根目录 README.md 中的桌面构建说明:
cargo run --release --package=ruffle_desktop可用于构建并运行,构建产物默认位于仓库根目录下的target/release/ruffle_desktop.exe。也就是说,在运行wix build之前,必须保证ruffle_desktop.exe已就绪;若只是要打包,也可以直接准备一个预编译的 exe 放在上述路径。
注意:
ruffle.wxs中引用的是$(CargoBuildDir)/ruffle_desktop.exe(见 ruffle.wxs),因此打包前请确认该 exe 文件存在且为 Windows 目标平台产物。
三、环境变量:RUFFLE_VERSION 与 CARGO_BUILD_DIR
MSI 构建依赖两个环境变量,其中一个是必需的。
RUFFLE_VERSION(必需)
该变量指定 MSI 所包含的 Ruffle 版本号,会直接写入 Windows Installer 的Version属性(见 ruffle.wxs),用于 Windows 的版本比较与升级判定。取值规则如下:
- 格式必须为
1.2.3或1.2.3.4(点分四段); - 注意:第四段数字会被 Windows 忽略——Windows 的“是否为相同或更新版本”检查只比较前三段,因此不要指望通过修改第四段来发布“更新版本”,它不影响升级判定。
在构建命令中通常以内联环境变量的方式传入,例如:
RUFFLE_VERSION="1.2.3" wix build ruffle.wxs ...CARGO_BUILD_DIR(可选)
该变量指定包含ruffle_desktop.exe的目录。默认值为../../../../target/release(相对于desktop/packages/windows/wix目录,即仓库根目录下的target/release)。ruffle.wxs中对应的逻辑如下(见 ruffle.wxs):
<?ifdef env.CARGO_BUILD_DIR?> <?define CargoBuildDir = "$(env.CARGO_BUILD_DIR)"?> <?else?> <?define CargoBuildDir = "../../../../target/release"?> <?endif?>即:如果设置了CARGO_BUILD_DIR环境变量则优先使用,否则回退到默认的../../../../target/release。当你的 exe 输出到自定义目录(例如 CI 流水线中的临时目录)时,可通过该变量覆盖默认路径,无需改动.wxs文件。
四、构建命令与常用参数
进入desktop/packages/windows/wix目录后,执行以下命令生成 x64 架构的 MSI:
wix build ruffle.wxs -ext WixToolset.UI.wixext -ext WixToolset.Util.wixext -arch x64其中:
| 参数 | 说明 |
|---|---|
ruffle.wxs | 主安装脚本文件,WiX 编译入口 |
-ext WixToolset.UI.wixext | 引入 UI 扩展(构建向导界面所需) |
-ext WixToolset.Util.wixext | 引入 Util 扩展(util:PermissionEx等所需) |
-arch x64 | 目标 CPU 架构,决定安装目录与注册表视图 |
README 还给出了三个可选参数:
-arch x86:将 MSI 标记为 x86 架构,此时安装目录会落在Program Files (x86)等 32 位路径下(由ProgramFiles6432Folder标准目录决定,详见下文);-pdbtype none:禁用.wixpdb(WiX 调试数据库)文件的生成,若不需要调试符号可加上此参数减小构建产物;-o foo.msi:指定 MSI 输出文件名与路径,默认输出到当前目录。
组合示例——生成 x86 架构、不带 wixpdb、自定义输出路径的 MSI:
wix build ruffle.wxs -ext WixToolset.UI.wixext -ext WixToolset.Util.wixext -arch x86 -pdbtype none -o dist/Ruffle-Setup-x86.msi五、深入解析 ruffle.wxs:安装包配置拆解
ruffle.wxs是整个 MSI 的“心脏”。下面按安装包生命周期逐层拆解其配置。
5.1 Package 元数据与升级策略
<Package Name='Ruffle' UpgradeCode='$(var.UpgradeCode)' Manufacturer='Ruffle LLC' Language='1033' Codepage='65001' Version='$(env.RUFFLE_VERSION)' InstallerVersion='500' Compressed='yes'>Name:安装包显示名Ruffle;UpgradeCode:升级码,用于跨版本识别“同一个产品”。固定值C6A4BA50-FA08-4B87-9B55-D81A1C730D25定义于文件顶部(见 ruffle.wxs),注释说明:如需将 MSI 作为“不同的包”安装(例如本地测试同一版本),可修改此 UpgradeCode——修改后 Windows 会把它当作全新产品,允许与正式版共存;Manufacturer:厂商名Ruffle LLC;Language/Codepage:语言 1033(en-US)与 UTF-8 代码页 65001;Version:直接取自$(env.RUFFLE_VERSION)环境变量,即上文必须设置的版本号;InstallerVersion:所需 Windows Installer 最低版本 500(Windows Installer 5.0,随 Windows 7 及以后系统提供);Compressed='yes':全部文件压缩进 MSI(配合<Media EmbedCab='yes'>,见 ruffle.wxs),得到单一自包含的.msi文件。
升级逻辑由<MajorUpgrade>控制(见 ruffle.wxs):
<MajorUpgrade Schedule='afterInstallInitialize' DowngradeErrorMessage='A newer version of Ruffle is already installed. Setup will now exit.' AllowSameVersionUpgrades="yes"/>Schedule='afterInstallInitialize':在安装初始化后执行主要升级,可处理文件占用等场景;DowngradeErrorMessage:检测到已安装更新版本时显示的提示文案(“已安装更新版本的 Ruffle,安装程序将退出”);AllowSameVersionUpgrades="yes":允许同版本号覆盖安装,配合前文“第四段版本号被忽略”的特性使用。
5.2 目录结构与组件
目录树定义如下(见 ruffle.wxs):
ProgramFiles6432Folder (64 位:Program Files;32 位:Program Files (x86)) └── INSTALLFOLDER (ruffle) ├── EnsureDirectoryWritable 组件:授权 Users 组 GenericAll 写权限(util:PermissionEx) ├── License 组件:安装 LICENSE.md 许可证文件 └── Bin (bin) ├── Path 组件:把 [Bin] 写入系统 PATH 环境变量 └── binary0 组件:安装 ruffle.exe + 开始菜单快捷方式几个值得注意的实现细节:
ProgramFiles6432Folder:由-arch参数决定其最终解析路径——x64 安装到Program Files,x86 安装到Program Files (x86),这正是 README 中“-arch x86会安装到 Program Files (x86)”的底层原因;EnsureDirectoryWritable:通过util:PermissionEx User="Users" GenericAll="yes"授予所有 Users 对安装目录的写权限,方便普通用户在安装后写入数据(例如向 Ruffle 目录放置 SWF 文件)而不需要管理员权限;Path组件:使用<Environment>元素把[Bin](即...\ruffle\bin)追加到系统级 PATH,Part='last'表示追加在末尾,Permanent='no'表示卸载时移除,Action='set'、System='yes'表示写入系统环境变量。该组件默认随主功能安装,但可在 UI 中作为独立子功能控制(见 5.5);binary0组件:安装ruffle.exe,同时创建ProgramMenuFolder中的“Ruffle”开始菜单快捷方式(Advertise='yes'广告式快捷方式,图标取自Icon.ico,见 ruffle.wxs,图标源文件为仓库根目录 desktop/assets/favicon.ico);DesktopShortcut组件:桌面快捷方式,带Condition="INSTALLDESKTOPSHORTCUT"条件——只有用户在自定义向导中勾选了“在桌面创建快捷方式”复选框(对应属性INSTALLDESKTOPSHORTCUT,默认值为 1,见 ruffle.wxs)才会安装。由于快捷方式不能作为组件 KeyPath,源码中特意写入了一个 HKCU 注册表值作为 KeyPath 并附注释说明这一“必要的技巧”(见 ruffle.wxs)。
5.3 文件关联:.swf / .spl / .ruf
Associations组件为 Ruffle 声明了三种文件类型关联(见 ruffle.wxs):
| ProgId | 扩展名 | 说明 |
|---|---|---|
Ruffle.swf | .swf | Flash 影片,ContentTypeapplication/x-shockwave-flash |
Ruffle.spl | .spl | Flash 影片(旧式 FutureSplash 扩展名) |
Ruffle.ruf | .ruf | Ruffle Bundle,ContentTypeapplication/x.ruffle-bundle+zip |
每个 ProgId 都注册了open动词,执行命令为ruffle.exe "%1"(Argument='"%1"',见 ruffle.wxs)。同时通过HKCR\.swf\OpenWithProgids等注册表值把 Ruffle 加入对应扩展名的“打开方式”列表(见 ruffle.wxs)。
源码注释对关联行为有重要说明(见 ruffle.wxs):这些注册只表示“Ruffle 可以打开这些文件”,Windows 不一定会立即把默认打开程序切换为 Ruffle,更常见的是用户下次双击 SWF 时被询问选择哪个程序。同时,ApplicationInfo组件进一步在HKCR\Applications\ruffle.exe下注册了FriendlyAppName(在“打开方式”对话框中显示为 “Ruffle” 而非ruffle.exe)以及SupportedTypes(.swf/.spl/.ruf)(见 ruffle.wxs)。注释中还特别提醒:Windows 仅凭 exe 文件名来匹配这些关联信息,一旦用户把ruffle.exe重命名,这些“打开方式”条目便会失效。
5.4 卸载信息与控制面板属性
SetProperty Id='ARPINSTALLLOCATION' Value='[APPLICATIONFOLDER]' After='CostFinalize':把安装位置写入 ARP(添加/删除程序)信息(见 ruffle.wxs);ARPPRODUCTICON:控制面板中显示的产品图标Icon.ico;ARPHELPLINK:帮助链接指向https://ruffle.rs;dialog.wxi中设置ARPNOMODIFY=1(见 dialog.wxi):隐藏“修改”按钮,安装后只允许修复/卸载。
5.5 Feature 功能树
<Feature Id='Binaries' Title='Application' Description='Installs the Ruffle desktop application' ...> <!-- EnsureDirectoryWritable / License / binary0 / Associations / ApplicationInfo / DesktopShortcut --> <Feature Id='Environment' Title='PATH Environment Variable' Description='Add the install location of the Ruffle executable to the PATH system environment variable...'> <ComponentRef Id='Path'/> </Feature> </Feature>外层功能Binaries(应用程序本体)为必装项(Level='1'),内部嵌套子功能Environment(是否把 Ruffle 目录加入 PATH)——由于Display='expand'且子功能Level='1'默认选中,用户在自定义安装界面中可展开并取消勾选“PATH 环境变量”功能,实现按需安装。
六、自定义安装向导:dialog.wxi 与 WixUI_InstallDir_NoLicense
MSI 并未使用 WiX 默认向导,而是通过dialog.wxi定制了一套名为WixUI_InstallDir_NoLicense的界面(即“可选安装目录、无许可证页”的变体),并在ruffle.wxs中引用:
<ui:WixUI Id="WixUI_InstallDir_NoLicense" InstallDirectory="INSTALLFOLDER"/> <WixVariable Id="WixUIBannerBmp" Value="banner.png"/> <WixVariable Id="WixUIDialogBmp" Value="dialog.png"/>- 安装目录固定绑定到
INSTALLFOLDER,用户可在向导中浏览/修改安装位置; - 界面横幅(顶部 370x44 区域的
BannerBitmap)与对话框背景分别来自 banner.png 和 dialog.png。
dialog.wxi的核心内容(见 dialog.wxi)包括:
针对三种架构(X86/X64/A64)生成的 UI 片段:通过
<?foreach WIXUIARCH in X86;X64;A64 ?>分别生成WixUI_InstallDir_NoLicense_X86等 UI,并在BrowseDlg(浏览目录)与RuffleInstallDirDlg的“下一步”按钮上挂钩WixUIValidatePath_$(WIXUIARCH)路径校验动作(Condition="NOT WIXUI_DONTVALIDATEPATH",可通过设置WIXUI_DONTVALIDATEPATH关闭校验)。自定义安装目录对话框
RuffleInstallDirDlg:这是一个 370x270 的标准 WiX 对话框(Next/Back/Cancel 按钮、标题/描述文本、横幅位图、路径编辑框PathEdit、ChangeFolder浏览按钮),并额外加入了一个桌面快捷方式复选框(见 dialog.wxi):<Control Id="DesktopShortcutCheckBox" Type="CheckBox" X="20" Y="160" Width="290" Height="17" Property="INSTALLDESKTOPSHORTCUT" CheckBoxValue="1" Text="Create a shortcut for this program on the desktop."/>该复选框直接绑定前文 5.2 中
DesktopShortcut组件的条件属性INSTALLDESKTOPSHORTCUT——勾选与否会实时决定桌面快捷方式是否被安装。完整的对话框流转序列(见 dialog.wxi 与各
Publish规则):- 首次安装:
WelcomeDlg → RuffleInstallDirDlg → VerifyReadyDlg → DiskCostDlg; - 维护(已安装):
MaintenanceWelcomeDlg → MaintenanceTypeDlg(修复/移除)→ RuffleInstallDirDlg → VerifyReadyDlg; - 补丁安装:
WelcomeDlg → VerifyReadyDlg; - 目录校验失败时会弹出
InvalidDirDlg;浏览目录通过BrowseDlg完成。
- 首次安装:
七、与桌面端构建产物的对应关系
MSI 打包并非孤立流程,它和ruffle_desktop的构建配置紧密相关:
- 可执行文件名:
ruffle.wxs安装的文件名是ruffle.exe,与 desktop/Cargo.toml 中winresource声明的OriginalFilename = "ruffle.exe"一致;该元数据段还声明了ProductName = "Ruffle"、FileDescription = "Adobe Flash Player emulator"、CompanyName = "Ruffle LLC"、LegalCopyright等 Windows 资源信息,与 MSI 包元数据(Name/Manufacturer)相互呼应; - 版本信息来源:
desktop/src/main.rs中RUFFLE_VERSION常量由CARGO_PKG_VERSION、Git 提交 SHA 等在编译期拼接生成(见 desktop/src/main.rs);而打包时要求手动设置的RUFFLE_VERSION环境变量则独立控制 MSI 版本号,二者需注意保持同步,避免安装包版本与程序内部版本不一致; - 许可证文件:MSI 安装的
License组件直接引用仓库根目录的 LICENSE.md(见 ruffle.wxs),即 Ruffle 的 Apache-2.0/MIT 双许可文本。
八、常见问题与注意事项
- 版本号格式错误导致构建失败:
RUFFLE_VERSION必须形如1.2.3或1.2.3.4,缺少段数或含非数字字符会导致wix build报错;且第四段不参与 Windows 版本比较,发布新版本时应递增前三段。 - exe 缺失:构建前务必确认
$(CARGO_BUILD_DIR)/ruffle_desktop.exe存在(默认../../../../target/release),否则打包会因找不到源文件失败。 - x86 与 x64 的选择:
-arch x64安装到Program Files,-arch x86安装到Program Files (x86);请与你的ruffle_desktop.exe实际目标平台保持一致。 - 同版本号无法“升级”:由于 Windows 忽略版本号第四段,连续发布两个
1.2.3.x包时需依赖AllowSameVersionUpgrades="yes"的覆盖安装语义;若希望并存测试,可修改 ruffle.wxs 中的UpgradeCode。 - 文件关联不生效:MSI 只负责注册“打开方式”候选与 ProgId,是否接管默认关联由 Windows 询问用户决定;且重命名
ruffle.exe会导致Open With中的条目失效(见 ruffle.wxs 注释)。 .wixpdb体积:不需要调试数据库时加上-pdbtype none可精简构建输出。
九、小结
Ruffle 的 Windows MSI 打包方案以 WiX v4 为工具链、以 ruffle.wxs 为配置核心,配合 dialog.wxi 的自定义向导,实现了安装目录选择、桌面快捷方式复选、.swf/.spl/.ruf文件关联、PATH 环境变量写入、主升级策略与Program Files目录权限等完整安装体验。只要遵循“先装 WiX 扩展、再构建ruffle_desktop.exe、设置RUFFLE_VERSION、执行wix build”四步流程,即可在本地或 CI 中稳定产出可分发、可升级的.msi安装包。
【免费下载链接】ruffleA Flash Player emulator written in Rust项目地址: https://gitcode.com/GitHub_Trending/ru/ruffle
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考