# cargo-wix 打包与 WiX 常用修改指南 本文档说明本项目如何使用 `cargo-wix` 生成 Windows MSI 安装包,以及常见 WiX 配置的修改方法。当前项目的安装配置文件是 `wix/main.wxs`,Rust 包信息来自 `Cargo.toml`。 ## 1. 当前项目打包方式 本项目使用: - Rust/Cargo 构建 release 可执行文件 - `cargo-wix` 读取 `Cargo.toml` 和 `wix/main.wxs` - WiX Toolset v3 编译并链接生成 `.msi` 当前可执行文件配置在 `Cargo.toml`: ```toml [[bin]] name = "ESkinPlayer" path = "src/main.rs" ``` 当前 WiX 元信息: ```toml [package.metadata.wix] eula = false ``` 当前 MSI 默认生成到: ```text target\wix\eskin-model-player--x86_64.msi ``` 例如: ```text target\wix\eskin-model-player-5.0.0-x86_64.msi ``` ## 2. 环境准备 需要安装: 1. Rust toolchain 2. WiX Toolset v3 3. cargo-wix 检查 Rust: ```powershell rustc --version cargo --version ``` 安装 `cargo-wix`: ```powershell cargo install cargo-wix ``` 检查 `cargo-wix`: ```powershell cargo wix --help ``` 本机常见 WiX v3 路径: ```text C:\Program Files (x86)\WiX Toolset v3.14\bin ``` 检查 WiX 工具是否存在: ```powershell Test-Path "C:\Program Files (x86)\WiX Toolset v3.14\bin\candle.exe" Test-Path "C:\Program Files (x86)\WiX Toolset v3.14\bin\light.exe" ``` ## 3. 常用打包命令 进入项目目录: ```powershell cd D:\eskin-player ``` 清理旧的 WiX 输出: ```powershell cargo wix clean ``` 正常打包: ```powershell cargo wix --bin-path "C:\Program Files (x86)\WiX Toolset v3.14\bin" --nocapture ``` 说明: - `--bin-path` 指定 WiX Toolset 的 `bin` 目录。 - `--nocapture` 显示 `candle.exe` 和 `light.exe` 的详细输出,排查错误时建议加上。 - 默认会先执行 `cargo build --release`。 - 默认输出到 `target\wix`。 查看生成的 MSI: ```powershell Get-ChildItem target\wix\*.msi ``` 指定输出目录: ```powershell cargo wix --bin-path "C:\Program Files (x86)\WiX Toolset v3.14\bin" --output dist\ ``` 指定输出文件名: ```powershell cargo wix --bin-path "C:\Program Files (x86)\WiX Toolset v3.14\bin" --output dist\ESkinPlayer.msi ``` 只打包,不重新构建 Rust: ```powershell cargo wix --bin-path "C:\Program Files (x86)\WiX Toolset v3.14\bin" --no-build --target-bin-dir target\release ``` 打包后立即安装: ```powershell cargo wix --bin-path "C:\Program Files (x86)\WiX Toolset v3.14\bin" --install ``` ## 4. 重要文件说明 ### Cargo.toml `Cargo.toml` 决定包名、版本、描述、作者、二进制名称等。 常见字段: ```toml [package] name = "eskin-model-player" version = "5.0.0" authors = ["JOYSONQUIN"] description = "Desktop pressure sensor visualization and playback application." ``` 这些字段会影响: - MSI 文件名 - 控制面板里的产品版本 - WiX 模板变量 修改版本号后重新打包: ```toml version = "5.0.1" ``` Windows Installer 的升级判断依赖版本号。发布新的安装包时建议递增版本号。 ### wix/main.wxs `wix/main.wxs` 是 WiX 主配置文件。它决定: - 安装包名称 - 安装范围 - 安装目录 - 包含哪些文件 - 是否写 PATH - 卸载行为 - UI 样式 - 升级规则 - 图标、EULA、快捷方式等 ## 5. Product 和 Package 典型结构: ```xml ``` 关键字段: - `Product/@Id='*'`:每次构建生成新的 ProductCode。 - `UpgradeCode`:同一个产品线必须保持稳定,不要随意修改。 - `Version='$(var.Version)'`:使用 `Cargo.toml` 的版本。 - `InstallScope`:安装范围,常见值是 `perUser` 或 `perMachine`。 - `InstallPrivileges`:权限要求,`limited` 表示不要求管理员权限,`elevated` 表示需要提升权限。 ## 6. per-user 和 per-machine 的区别 ### 当前用户安装:perUser 适合: - 不希望安装时弹管理员权限 - 应用只给当前用户使用 - 安装到用户目录,例如 `%LOCALAPPDATA%` - 写用户 PATH 或 HKCU 注册表 推荐配置: ```xml ``` 目录使用: ```xml ... ``` 环境变量使用用户级 PATH: ```xml ``` 注意: - 安装到用户目录的组件需要使用 `HKCU` 注册表项作为 `KeyPath`。 - 用户目录下的安装目录建议添加 `RemoveFolder`,否则 ICE64 会报错。 ### 所有用户安装:perMachine 适合: - 应用需要给所有用户使用 - 安装到 `Program Files` - 写系统 PATH - 写 HKLM 注册表 - 公司 IT 管理员部署 推荐配置: ```xml ``` 目录使用: ```xml ... ``` 64 位安装包通常使用: ```xml ``` 然后: ```xml ``` 系统 PATH: ```xml ``` 注意: - `perMachine` 通常需要管理员权限。 - 如果普通用户安装,会出现权限不足提示。 - 写 `Program Files` 和系统 PATH 都需要提升权限。 ## 7. 当前项目的 per-user 配置要点 当前项目已经改为当前用户安装: ```xml InstallScope='perUser' InstallPrivileges='limited' ``` 安装目录: ```xml ... ``` PATH 组件使用 HKCU registry key 作为 KeyPath: ```xml ``` 程序文件组件也使用 HKCU registry key 作为 KeyPath: ```xml ``` ## 8. Component、File、KeyPath 的基本规则 WiX 的核心概念: - `Directory`:安装目录。 - `Component`:安装和卸载的最小管理单元。 - `File`:要安装的文件。 - `RegistryValue`:要写入的注册表项。 - `KeyPath`:Windows Installer 用来判断组件是否已安装的关键路径。 常见规则: - 一个组件通常只放一个主要文件。 - 组件 GUID 一旦发布后不要随意修改。 - `perUser` 安装到用户目录时,建议用 `HKCU` registry key 作为 `KeyPath`。 - `perMachine` 安装到 Program Files 时,文件通常可以作为 `KeyPath`。 - 如果组件同时包含文件和注册表 KeyPath,WiX v3 通常不能用 `Guid='*'` 自动生成 GUID,需要写固定 GUID。 生成 GUID: ```powershell [guid]::NewGuid().ToString().ToUpper() ``` 示例: ```xml ... ``` ## 9. 添加文件 假设要安装一个 `README.txt` 到应用目录。 目录结构: ```text wix\ main.wxs README.txt ``` 添加组件: ```xml ``` 然后在 `Feature` 里引用: ```xml ``` 如果是 `perMachine` 安装,也可以简化为: ```xml ``` ## 10. 添加资源目录 如果程序运行时需要模型、图片、配置文件等资源,建议明确安装到应用目录下。 示例: ```xml ``` 引用: ```xml ``` 如果资源很多,不建议长期手写大量 ``。可以考虑: - 用 WiX Heat 自动收集目录 - 在构建脚本里生成 `.wxs` 片段 - 只把稳定的少量资源手写到 `main.wxs` ## 11. 修改安装目录 ### 改为当前用户目录 ```xml ... ``` 实际路径通常类似: ```text C:\Users\\AppData\Local\eskin-model-player ``` ### 改为 Program Files ```xml ... ``` 64 位项目推荐: ```xml ... ``` ## 12. 是否添加 PATH 当前项目有一个可选 Feature:把安装目录下的 `bin` 加入 PATH。 Feature: ```xml ``` 如果不希望修改 PATH,可以删除或注释: ```xml ``` 也可以把整个 `Environment` Feature 注释掉。 用户级 PATH: ```xml System='no' ``` 系统级 PATH: ```xml System='yes' ``` 注意: - 用户级 PATH 不需要管理员权限。 - 系统级 PATH 需要管理员权限。 - 安装后新开的终端才能看到新的 PATH。 - 已打开的 PowerShell/CMD 通常不会自动刷新环境变量。 ## 13. 添加开始菜单快捷方式 常见做法是在 `ProgramMenuFolder` 下创建快捷方式。 目录: ```xml ``` 在可执行文件组件里添加: ```xml ``` 如果是 per-user 安装,快捷方式组件也应该使用 HKCU registry key 作为 `KeyPath`。 ## 14. 添加桌面快捷方式 目录: ```xml ``` 快捷方式: ```xml ``` 桌面快捷方式不一定适合默认创建。更推荐放到可选 Feature,或者只创建开始菜单快捷方式。 ## 15. 修改控制面板图标 准备 `.ico` 文件,例如: ```text wix\Product.ico ``` 启用: ```xml ``` 注意: - `.ico` 最好包含多个尺寸,例如 16、32、48、256。 - 路径相对执行打包时的项目根目录。 ## 16. 添加 EULA 如果需要安装时显示许可协议: 1. 准备 RTF 文件,例如 `wix\Eula.rtf` 2. 修改 `Cargo.toml` ```toml [package.metadata.wix] eula = true ``` 3. 在 `wix/main.wxs` 中启用: ```xml ``` 如果当前使用 `WixUI_FeatureTree` 并跳过 EULA,需要检查 `` 里的 `Publish` 逻辑,避免安装流程跳转冲突。 ## 17. 修改安装 UI 当前项目使用: ```xml ... ``` 常见 UI: - `WixUI_Minimal`:最简单。 - `WixUI_InstallDir`:允许选择安装目录。 - `WixUI_FeatureTree`:允许选择 Feature。 - `WixUI_Advanced`:更完整的高级安装流程。 如果要允许用户改安装路径,常用: ```xml ``` ## 18. 升级策略 当前项目使用: ```xml ``` 含义: - 安装新版本时自动卸载旧版本。 - 不允许安装更旧版本覆盖新版本。 - `UpgradeCode` 必须保持不变。 - `Version` 必须递增。 Windows Installer 版本规则: - 通常只比较前三段版本号:`Major.Minor.Build` - `5.0.0` 到 `5.0.1` 是升级 - 只重打同一个 `5.0.0` 可能不会触发正常升级 发布新版时建议: ```toml version = "5.0.1" ``` ## 19. 签名 MSI 未签名 MSI 在 Windows 上可能触发安全提示。正式发布建议签名。 `cargo-wix` 支持 `sign` 子命令,也可以在生成 MSI 后用 `signtool.exe`。 示例: ```powershell signtool sign /fd SHA256 /tr http://timestamp.digicert.com /td SHA256 /a target\wix\eskin-model-player-5.0.0-x86_64.msi ``` 实际签名命令取决于证书来源: - 本机证书 - PFX 文件 - 硬件 token - 公司代码签名服务 ## 20. 常见错误与处理 ### 权限不足 错误示例: ```text You do not have sufficient privileges to complete this installation for all users of the machine. ``` 常见原因: - `InstallScope='perMachine'` - 安装到 `ProgramFilesFolder` - 写系统 PATH:`System='yes'` - 写 HKLM 注册表 解决: - 以管理员身份运行 MSI - 或改成 `perUser` - 或安装到 `LocalAppDataFolder` - 或把 PATH 改为 `System='no'` ### ICE38 错误示例: ```text ICE38: Component ... installs to user profile. It must use a registry key under HKCU as its KeyPath, not a file. ``` 原因: - 组件安装到用户目录 - 但组件使用文件作为 `KeyPath` 解决: ```xml ``` 并移除 `File` 上的: ```xml KeyPath='yes' ``` ### ICE64 错误示例: ```text ICE64: The directory Bin is in the user profile but is not listed in the RemoveFile table. ``` 原因: - 用户目录下创建了目录 - 卸载时没有明确清理 解决: ```xml ``` ### CNDL0230 错误示例: ```text The Component/@Guid attribute's value '*' is not valid for this component because it does not meet the criteria for having an automatically generated guid. ``` 原因: - 组件里有文件 - 但 KeyPath 是 registry value - WiX v3 不能自动生成这种组件 GUID 解决: 生成固定 GUID: ```powershell [guid]::NewGuid().ToString().ToUpper() ``` 然后写入: ```xml ``` ### ICE91 警告示例: ```text ICE91: The file 'exe0' will be installed to the per user directory ... ``` 原因: - 文件安装到用户目录 - ICE 提醒如果该包被当作 per-machine 安装,文件不会复制到每个用户的 profile 处理: - 如果安装包明确是 `perUser`,通常可以忽略。 - 如果目标是 `perMachine`,应改用 `ProgramFilesFolder`,不要安装到用户 profile。 ### 新 MSI 没有覆盖旧 MSI 常见原因: - `Cargo.toml` 版本号没变 - `UpgradeCode` 改了 - 旧版本是 per-machine,新版本是 per-user 解决: - 发布时递增版本号 - 保持 `UpgradeCode` 不变 - 如果旧版本是 per-machine,先用管理员权限卸载旧版本 ## 21. 调试 MSI 安装 生成详细安装日志: ```powershell msiexec /i target\wix\eskin-model-player-5.0.0-x86_64.msi /l*v install.log ``` 静默安装: ```powershell msiexec /i target\wix\eskin-model-player-5.0.0-x86_64.msi /qn /l*v install.log ``` 卸载: ```powershell msiexec /x target\wix\eskin-model-player-5.0.0-x86_64.msi /l*v uninstall.log ``` 如果安装失败,优先查看日志里: ```text Return value 3 ``` 它附近通常是真正失败原因。 ## 22. 推荐发布流程 1. 更新 `Cargo.toml` 版本号。 2. 确认 `wix/main.wxs` 的安装范围符合发布目标。 3. 执行 release 构建和 MSI 打包。 4. 在干净机器或干净用户环境中测试安装。 5. 测试启动程序。 6. 测试卸载后文件、快捷方式、PATH 是否清理干净。 7. 正式发布前对 MSI 签名。 命令: ```powershell cd D:\eskin-player cargo wix clean cargo wix --bin-path "C:\Program Files (x86)\WiX Toolset v3.14\bin" --nocapture ``` 验证: ```powershell Get-ChildItem target\wix\*.msi msiexec /i target\wix\eskin-model-player-5.0.0-x86_64.msi /l*v install.log ``` ## 23. 本项目常用修改清单 ### 改包名 修改 `Product/@Name`: ```xml Name='eskin-model-player' ``` 以及 `Cargo.toml`: ```toml name = "eskin-model-player" ``` ### 改显示厂商 修改: ```xml Manufacturer='JOYSONQUIN' ``` 以及: ```toml authors = ["JOYSONQUIN"] ``` ### 改安装目录名 修改: ```xml ``` ### 改可执行文件名 修改 `Cargo.toml`: ```toml [[bin]] name = "ESkinPlayer" ``` 同步修改 WiX: ```xml ``` ### 关闭 PATH 写入 删除或注释: ```xml ``` 也可以删除整个 `Environment` Feature。 ### 从 per-user 改回 per-machine 修改: ```xml InstallScope='perMachine' InstallPrivileges='elevated' ``` 安装目录改为: ```xml ``` PATH 改为: ```xml System='yes' ``` 注意: - 这会重新要求管理员权限。 - 如果已经发布过 per-user 版本,切换安装范围前需要测试升级和卸载路径。 ## 24. 维护注意事项 - `UpgradeCode` 是产品线标识,正常发布不要改。 - 发布新版本时递增 `Cargo.toml` 的 `version`。 - 已发布组件的 `Guid` 不要随意变更。 - 用户目录安装使用 `HKCU` registry key 作为 `KeyPath`。 - 系统目录安装通常需要管理员权限。 - 修改 PATH 后要测试安装和卸载。 - 加文件后必须在 `Feature` 中添加 `ComponentRef`,否则不会被安装。 - WiX 报错时优先看 `candle` 还是 `light` 阶段: - `candle`:XML 结构、语法、GUID、路径等编译错误。 - `light`:链接、ICE 校验、MSI 表规则问题。