1061 lines
21 KiB
Markdown
1061 lines
21 KiB
Markdown
# 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-<version>-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='*'
|
||
Name='eskin-model-player'
|
||
UpgradeCode='7CEF316B-BE23-4533-B4B2-87D06D2230B5'
|
||
Manufacturer='JOYSONQUIN'
|
||
Language='1033'
|
||
Codepage='1252'
|
||
Version='$(var.Version)'>
|
||
|
||
<Package Id='*'
|
||
Keywords='Installer'
|
||
Description='Desktop pressure sensor visualization and playback application.'
|
||
Manufacturer='JOYSONQUIN'
|
||
InstallerVersion='450'
|
||
Languages='1033'
|
||
Compressed='yes'
|
||
InstallScope='perUser'
|
||
InstallPrivileges='limited'
|
||
SummaryCodepage='1252'/>
|
||
</Product>
|
||
```
|
||
|
||
关键字段:
|
||
|
||
- `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
|
||
<Package
|
||
...
|
||
InstallScope='perUser'
|
||
InstallPrivileges='limited'/>
|
||
```
|
||
|
||
目录使用:
|
||
|
||
```xml
|
||
<Directory Id='TARGETDIR' Name='SourceDir'>
|
||
<Directory Id='LocalAppDataFolder'>
|
||
<Directory Id='APPLICATIONFOLDER' Name='eskin-model-player'>
|
||
...
|
||
</Directory>
|
||
</Directory>
|
||
</Directory>
|
||
```
|
||
|
||
环境变量使用用户级 PATH:
|
||
|
||
```xml
|
||
<Environment
|
||
Id='PATH'
|
||
Name='PATH'
|
||
Value='[Bin]'
|
||
Permanent='no'
|
||
Part='last'
|
||
Action='set'
|
||
System='no'/>
|
||
```
|
||
|
||
注意:
|
||
|
||
- 安装到用户目录的组件需要使用 `HKCU` 注册表项作为 `KeyPath`。
|
||
- 用户目录下的安装目录建议添加 `RemoveFolder`,否则 ICE64 会报错。
|
||
|
||
### 所有用户安装:perMachine
|
||
|
||
适合:
|
||
|
||
- 应用需要给所有用户使用
|
||
- 安装到 `Program Files`
|
||
- 写系统 PATH
|
||
- 写 HKLM 注册表
|
||
- 公司 IT 管理员部署
|
||
|
||
推荐配置:
|
||
|
||
```xml
|
||
<Package
|
||
...
|
||
InstallScope='perMachine'
|
||
InstallPrivileges='elevated'/>
|
||
```
|
||
|
||
目录使用:
|
||
|
||
```xml
|
||
<Directory Id='TARGETDIR' Name='SourceDir'>
|
||
<Directory Id='ProgramFilesFolder'>
|
||
<Directory Id='APPLICATIONFOLDER' Name='eskin-model-player'>
|
||
...
|
||
</Directory>
|
||
</Directory>
|
||
</Directory>
|
||
```
|
||
|
||
64 位安装包通常使用:
|
||
|
||
```xml
|
||
<?if $(sys.BUILDARCH) = x64 or $(sys.BUILDARCH) = arm64 ?>
|
||
<?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
|
||
<?else ?>
|
||
<?define PlatformProgramFilesFolder = "ProgramFilesFolder" ?>
|
||
<?endif ?>
|
||
```
|
||
|
||
然后:
|
||
|
||
```xml
|
||
<Directory Id='$(var.PlatformProgramFilesFolder)' Name='PFiles'>
|
||
```
|
||
|
||
系统 PATH:
|
||
|
||
```xml
|
||
<Environment
|
||
Id='PATH'
|
||
Name='PATH'
|
||
Value='[Bin]'
|
||
Permanent='no'
|
||
Part='last'
|
||
Action='set'
|
||
System='yes'/>
|
||
```
|
||
|
||
注意:
|
||
|
||
- `perMachine` 通常需要管理员权限。
|
||
- 如果普通用户安装,会出现权限不足提示。
|
||
- 写 `Program Files` 和系统 PATH 都需要提升权限。
|
||
|
||
## 7. 当前项目的 per-user 配置要点
|
||
|
||
当前项目已经改为当前用户安装:
|
||
|
||
```xml
|
||
InstallScope='perUser'
|
||
InstallPrivileges='limited'
|
||
```
|
||
|
||
安装目录:
|
||
|
||
```xml
|
||
<Directory Id='TARGETDIR' Name='SourceDir'>
|
||
<Directory Id='LocalAppDataFolder'>
|
||
<Directory Id='APPLICATIONFOLDER' Name='eskin-model-player'>
|
||
<Directory Id='Bin' Name='bin'>
|
||
...
|
||
</Directory>
|
||
</Directory>
|
||
</Directory>
|
||
</Directory>
|
||
```
|
||
|
||
PATH 组件使用 HKCU registry key 作为 KeyPath:
|
||
|
||
```xml
|
||
<Component Id='Path' Guid='FD230ABD-75B9-47D4-870B-CF2EA72B76BE'>
|
||
<RegistryValue
|
||
Root='HKCU'
|
||
Key='Software\JOYSONQUIN\eskin-model-player'
|
||
Name='PathComponent'
|
||
Type='integer'
|
||
Value='1'
|
||
KeyPath='yes'/>
|
||
<RemoveFolder Id='RemoveBinFolder' Directory='Bin' On='uninstall'/>
|
||
<RemoveFolder Id='RemoveApplicationFolder' Directory='APPLICATIONFOLDER' On='uninstall'/>
|
||
<Environment
|
||
Id='PATH'
|
||
Name='PATH'
|
||
Value='[Bin]'
|
||
Permanent='no'
|
||
Part='last'
|
||
Action='set'
|
||
System='no'/>
|
||
</Component>
|
||
```
|
||
|
||
程序文件组件也使用 HKCU registry key 作为 KeyPath:
|
||
|
||
```xml
|
||
<Component Id='binary0' Guid='302CAFB5-6951-426B-BC5A-988C351A2CF2'>
|
||
<RegistryValue
|
||
Root='HKCU'
|
||
Key='Software\JOYSONQUIN\eskin-model-player'
|
||
Name='BinaryComponent'
|
||
Type='integer'
|
||
Value='1'
|
||
KeyPath='yes'/>
|
||
<File
|
||
Id='exe0'
|
||
Name='ESkinPlayer.exe'
|
||
DiskId='1'
|
||
Source='$(var.CargoTargetBinDir)\ESkinPlayer.exe'/>
|
||
</Component>
|
||
```
|
||
|
||
## 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
|
||
<Component Id='binary0' Guid='302CAFB5-6951-426B-BC5A-988C351A2CF2'>
|
||
...
|
||
</Component>
|
||
```
|
||
|
||
## 9. 添加文件
|
||
|
||
假设要安装一个 `README.txt` 到应用目录。
|
||
|
||
目录结构:
|
||
|
||
```text
|
||
wix\
|
||
main.wxs
|
||
README.txt
|
||
```
|
||
|
||
添加组件:
|
||
|
||
```xml
|
||
<Component Id='ReadmeFile' Guid='PUT-GUID-HERE'>
|
||
<RegistryValue
|
||
Root='HKCU'
|
||
Key='Software\JOYSONQUIN\eskin-model-player'
|
||
Name='ReadmeComponent'
|
||
Type='integer'
|
||
Value='1'
|
||
KeyPath='yes'/>
|
||
<File
|
||
Id='ReadmeTxt'
|
||
Name='README.txt'
|
||
DiskId='1'
|
||
Source='wix\README.txt'/>
|
||
</Component>
|
||
```
|
||
|
||
然后在 `Feature` 里引用:
|
||
|
||
```xml
|
||
<ComponentRef Id='ReadmeFile'/>
|
||
```
|
||
|
||
如果是 `perMachine` 安装,也可以简化为:
|
||
|
||
```xml
|
||
<Component Id='ReadmeFile' Guid='PUT-GUID-HERE'>
|
||
<File
|
||
Id='ReadmeTxt'
|
||
Name='README.txt'
|
||
DiskId='1'
|
||
Source='wix\README.txt'
|
||
KeyPath='yes'/>
|
||
</Component>
|
||
```
|
||
|
||
## 10. 添加资源目录
|
||
|
||
如果程序运行时需要模型、图片、配置文件等资源,建议明确安装到应用目录下。
|
||
|
||
示例:
|
||
|
||
```xml
|
||
<Directory Id='AssetsFolder' Name='assets'>
|
||
<Component Id='AssetConfig' Guid='PUT-GUID-HERE'>
|
||
<RegistryValue
|
||
Root='HKCU'
|
||
Key='Software\JOYSONQUIN\eskin-model-player'
|
||
Name='AssetConfigComponent'
|
||
Type='integer'
|
||
Value='1'
|
||
KeyPath='yes'/>
|
||
<File
|
||
Id='AssetConfigJson'
|
||
Name='config.json'
|
||
DiskId='1'
|
||
Source='assets\config.json'/>
|
||
</Component>
|
||
</Directory>
|
||
```
|
||
|
||
引用:
|
||
|
||
```xml
|
||
<ComponentRef Id='AssetConfig'/>
|
||
```
|
||
|
||
如果资源很多,不建议长期手写大量 `<File>`。可以考虑:
|
||
|
||
- 用 WiX Heat 自动收集目录
|
||
- 在构建脚本里生成 `.wxs` 片段
|
||
- 只把稳定的少量资源手写到 `main.wxs`
|
||
|
||
## 11. 修改安装目录
|
||
|
||
### 改为当前用户目录
|
||
|
||
```xml
|
||
<Directory Id='TARGETDIR' Name='SourceDir'>
|
||
<Directory Id='LocalAppDataFolder'>
|
||
<Directory Id='APPLICATIONFOLDER' Name='eskin-model-player'>
|
||
...
|
||
</Directory>
|
||
</Directory>
|
||
</Directory>
|
||
```
|
||
|
||
实际路径通常类似:
|
||
|
||
```text
|
||
C:\Users\<user>\AppData\Local\eskin-model-player
|
||
```
|
||
|
||
### 改为 Program Files
|
||
|
||
```xml
|
||
<Directory Id='TARGETDIR' Name='SourceDir'>
|
||
<Directory Id='ProgramFilesFolder'>
|
||
<Directory Id='APPLICATIONFOLDER' Name='eskin-model-player'>
|
||
...
|
||
</Directory>
|
||
</Directory>
|
||
</Directory>
|
||
```
|
||
|
||
64 位项目推荐:
|
||
|
||
```xml
|
||
<Directory Id='TARGETDIR' Name='SourceDir'>
|
||
<Directory Id='ProgramFiles64Folder'>
|
||
<Directory Id='APPLICATIONFOLDER' Name='eskin-model-player'>
|
||
...
|
||
</Directory>
|
||
</Directory>
|
||
</Directory>
|
||
```
|
||
|
||
## 12. 是否添加 PATH
|
||
|
||
当前项目有一个可选 Feature:把安装目录下的 `bin` 加入 PATH。
|
||
|
||
Feature:
|
||
|
||
```xml
|
||
<Feature
|
||
Id='Environment'
|
||
Title='PATH Environment Variable'
|
||
Description='Add the install location of the [ProductName] executable to the PATH system environment variable.'
|
||
Level='1'
|
||
Absent='allow'>
|
||
<ComponentRef Id='Path'/>
|
||
</Feature>
|
||
```
|
||
|
||
如果不希望修改 PATH,可以删除或注释:
|
||
|
||
```xml
|
||
<ComponentRef Id='Path'/>
|
||
```
|
||
|
||
也可以把整个 `Environment` Feature 注释掉。
|
||
|
||
用户级 PATH:
|
||
|
||
```xml
|
||
System='no'
|
||
```
|
||
|
||
系统级 PATH:
|
||
|
||
```xml
|
||
System='yes'
|
||
```
|
||
|
||
注意:
|
||
|
||
- 用户级 PATH 不需要管理员权限。
|
||
- 系统级 PATH 需要管理员权限。
|
||
- 安装后新开的终端才能看到新的 PATH。
|
||
- 已打开的 PowerShell/CMD 通常不会自动刷新环境变量。
|
||
|
||
## 13. 添加开始菜单快捷方式
|
||
|
||
常见做法是在 `ProgramMenuFolder` 下创建快捷方式。
|
||
|
||
目录:
|
||
|
||
```xml
|
||
<Directory Id='ProgramMenuFolder'>
|
||
<Directory Id='ApplicationProgramsFolder' Name='eskin-model-player'/>
|
||
</Directory>
|
||
```
|
||
|
||
在可执行文件组件里添加:
|
||
|
||
```xml
|
||
<Shortcut
|
||
Id='ApplicationStartMenuShortcut'
|
||
Directory='ApplicationProgramsFolder'
|
||
Name='ESkinPlayer'
|
||
WorkingDirectory='Bin'
|
||
Advertise='no'
|
||
Target='[Bin]ESkinPlayer.exe'/>
|
||
|
||
<RemoveFolder Id='RemoveApplicationProgramsFolder' Directory='ApplicationProgramsFolder' On='uninstall'/>
|
||
```
|
||
|
||
如果是 per-user 安装,快捷方式组件也应该使用 HKCU registry key 作为 `KeyPath`。
|
||
|
||
## 14. 添加桌面快捷方式
|
||
|
||
目录:
|
||
|
||
```xml
|
||
<Directory Id='DesktopFolder' Name='Desktop'/>
|
||
```
|
||
|
||
快捷方式:
|
||
|
||
```xml
|
||
<Shortcut
|
||
Id='ApplicationDesktopShortcut'
|
||
Directory='DesktopFolder'
|
||
Name='ESkinPlayer'
|
||
WorkingDirectory='Bin'
|
||
Advertise='no'
|
||
Target='[Bin]ESkinPlayer.exe'/>
|
||
```
|
||
|
||
桌面快捷方式不一定适合默认创建。更推荐放到可选 Feature,或者只创建开始菜单快捷方式。
|
||
|
||
## 15. 修改控制面板图标
|
||
|
||
准备 `.ico` 文件,例如:
|
||
|
||
```text
|
||
wix\Product.ico
|
||
```
|
||
|
||
启用:
|
||
|
||
```xml
|
||
<Icon Id='ProductICO' SourceFile='wix\Product.ico'/>
|
||
<Property Id='ARPPRODUCTICON' Value='ProductICO'/>
|
||
```
|
||
|
||
注意:
|
||
|
||
- `.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
|
||
<WixVariable Id='WixUILicenseRtf' Value='wix\Eula.rtf'/>
|
||
```
|
||
|
||
如果当前使用 `WixUI_FeatureTree` 并跳过 EULA,需要检查 `<UI>` 里的 `Publish` 逻辑,避免安装流程跳转冲突。
|
||
|
||
## 17. 修改安装 UI
|
||
|
||
当前项目使用:
|
||
|
||
```xml
|
||
<UI>
|
||
<UIRef Id='WixUI_FeatureTree'/>
|
||
...
|
||
</UI>
|
||
```
|
||
|
||
常见 UI:
|
||
|
||
- `WixUI_Minimal`:最简单。
|
||
- `WixUI_InstallDir`:允许选择安装目录。
|
||
- `WixUI_FeatureTree`:允许选择 Feature。
|
||
- `WixUI_Advanced`:更完整的高级安装流程。
|
||
|
||
如果要允许用户改安装路径,常用:
|
||
|
||
```xml
|
||
<UIRef Id='WixUI_InstallDir'/>
|
||
<Property Id='WIXUI_INSTALLDIR' Value='APPLICATIONFOLDER'/>
|
||
```
|
||
|
||
## 18. 升级策略
|
||
|
||
当前项目使用:
|
||
|
||
```xml
|
||
<MajorUpgrade
|
||
Schedule='afterInstallInitialize'
|
||
DowngradeErrorMessage='A newer version of [ProductName] is already installed. Setup will now exit.'/>
|
||
```
|
||
|
||
含义:
|
||
|
||
- 安装新版本时自动卸载旧版本。
|
||
- 不允许安装更旧版本覆盖新版本。
|
||
- `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
|
||
<RegistryValue
|
||
Root='HKCU'
|
||
Key='Software\JOYSONQUIN\eskin-model-player'
|
||
Name='BinaryComponent'
|
||
Type='integer'
|
||
Value='1'
|
||
KeyPath='yes'/>
|
||
```
|
||
|
||
并移除 `File` 上的:
|
||
|
||
```xml
|
||
KeyPath='yes'
|
||
```
|
||
|
||
### ICE64
|
||
|
||
错误示例:
|
||
|
||
```text
|
||
ICE64: The directory Bin is in the user profile but is not listed in the RemoveFile table.
|
||
```
|
||
|
||
原因:
|
||
|
||
- 用户目录下创建了目录
|
||
- 卸载时没有明确清理
|
||
|
||
解决:
|
||
|
||
```xml
|
||
<RemoveFolder Id='RemoveBinFolder' Directory='Bin' On='uninstall'/>
|
||
<RemoveFolder Id='RemoveApplicationFolder' Directory='APPLICATIONFOLDER' On='uninstall'/>
|
||
```
|
||
|
||
### 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
|
||
<Component Id='binary0' Guid='302CAFB5-6951-426B-BC5A-988C351A2CF2'>
|
||
```
|
||
|
||
### 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
|
||
<Directory Id='APPLICATIONFOLDER' Name='eskin-model-player'>
|
||
```
|
||
|
||
### 改可执行文件名
|
||
|
||
修改 `Cargo.toml`:
|
||
|
||
```toml
|
||
[[bin]]
|
||
name = "ESkinPlayer"
|
||
```
|
||
|
||
同步修改 WiX:
|
||
|
||
```xml
|
||
<File
|
||
Id='exe0'
|
||
Name='ESkinPlayer.exe'
|
||
Source='$(var.CargoTargetBinDir)\ESkinPlayer.exe'/>
|
||
```
|
||
|
||
### 关闭 PATH 写入
|
||
|
||
删除或注释:
|
||
|
||
```xml
|
||
<ComponentRef Id='Path'/>
|
||
```
|
||
|
||
也可以删除整个 `Environment` Feature。
|
||
|
||
### 从 per-user 改回 per-machine
|
||
|
||
修改:
|
||
|
||
```xml
|
||
InstallScope='perMachine'
|
||
InstallPrivileges='elevated'
|
||
```
|
||
|
||
安装目录改为:
|
||
|
||
```xml
|
||
<Directory Id='$(var.PlatformProgramFilesFolder)' Name='PFiles'>
|
||
```
|
||
|
||
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 表规则问题。
|
||
|