用途
本技能用于为 XerahS 项目构建 Windows 安装程序,支持 x64 与 ARM64 两种架构,属于 Windows 打包、Inno Setup、构建产物校验等打包相关工作的专用技能。
主要能力
- 通过
build\windows\package-windows.ps1脚本执行 Windows 打包,脚本内部按 win-x64、win-arm64 顺序遍历构建。 - 处理构建过程中的文件锁定失败(如 CS2012: Cannot open '...ShareX.ImageEditor.dll' for writing,或文件被 VBCSCompiler、.NET Host、csc 占用)。
- 在 x64 成功但 ARM64 持续失败时,提供手动 ARM64 构建流程:预编译 ShareX.ImageEditor、手动 publish 主程序与插件、手动运行 Inno Setup 的 ISCC。
- 校验 dist 目录中安装包是否存在、大小与时间戳。
使用方式
准备阶段:构建固定的子模块版本,仅当任务要求时才通过操作者的 Git 包装器更新 ImageEditor;检查是否有其他构建共用这些输出,若发生锁则按 build-common 识别属于任务的锁持有者并仅清理受影响输出,常规打包不需要盲目终止进程或全面清理。
初始构建:运行 \.\build\windows\package-windows.ps1,脚本应以退出码 0 完成,并在 dist 文件夹生成两个安装程序。
文件锁失败的修复:按 build-common 仅停止经确认属于任务的锁持有者;若锁持续则清理受影响项目/输出目录;用下列命令单独预编译 ShareX.ImageEditor:
dotnet build 'ShareX.ImageEditor\src\ShareX.ImageEditor\ShareX.ImageEditor.csproj' -c Release -p:UseSharedCompilation=false /m:1
其中 /m:1 强制单线程构建,UseSharedCompilation=false 禁用 VBCSCompiler 服务器,之后重新运行打包脚本。
ARM64 兜底:若 ARM64 持续失败而 x64 成功,先恢复已确认的锁,预编译 ShareX.ImageEditor,然后手动发布 ARM64:
$root = (Get-Location).Path
$project = "$root\src\desktop\app\XerahS.App\XerahS.App.csproj"
$publishOutput = "$root\build\publish-temp-win-arm64"
dotnet publish $project -c Release -p:OS=Windows_NT -r win-arm64 -p:PublishSingleFile=false -p:SkipBundlePlugins=true -p:UseSharedCompilation=false --self-contained true -o $publishOutput
发布插件:
$pluginsDir = "$publishOutput\Plugins"
New-Item -ItemType Directory -Force -Path $pluginsDir | Out-Null
Get-ChildItem "$root\src\desktop\plugins" -Filter "*.csproj" -Recurse | ForEach-Object {
$pluginId = $_.BaseName
$pluginJsonPath = Join-Path $_.Directory.FullName "plugin.json"
if (Test-Path $pluginJsonPath) {
$json = Get-Content $pluginJsonPath -Raw | ConvertFrom-Json
if ($json.pluginId) { $pluginId = $json.pluginId }
}
Write-Host "Publishing plugin: $pluginId"
dotnet publish $_.FullName -c Release -r win-arm64 -p:UseSharedCompilation=false --self-contained false -o "$pluginsDir\$pluginId"
}
手动运行 Inno Setup:
$isccPath = "${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe"
$issScript = "$root\build\windows\XerahS-setup.iss"
$version = ([xml](Get-Content "$root\Directory.Build.props")).SelectSingleNode("//Version").InnerText.Trim()
$outputDir = "$root\dist"
& $isccPath "/dMyAppReleaseDirectory=$publishOutput" "/dOutputBaseFilename=XerahS-$version-win-arm64" "/dOutputDir=$outputDir" $issScript
校验:
Get-ChildItem 'dist' -Filter '*.exe' | Select-Object Name, Length, LastWriteTime | Format-Table -AutoSize
期望输出中,XerahS-{version}-win-arm64.exe 与 XerahS-{version}-win-x64.exe 大小约为 55-60MB,且时间为当天。
适用场景
适用于 XerahS 的 Windows 打包、Inno Setup 打包、构建产物检查,以及需要排查 ShareX.ImageEditor 多 TFM 并行编译引发的文件锁问题的构建环境。
限制与注意事项
- 必须顺序构建,绝不可同时运行两个构建。ShareX.ImageEditor 面向多个 TFM(net9.0、net10.0、net9.0-windows10.0.26100.0、net10.0-windows10.0.26100.0),MSBuild 并行会让它们在同一个 ShareX.ImageEditor.dll 输出路径上竞争,产生 CS2012 文件锁错误。package-windows.ps1 已按 win-x64、win-arm64 顺序 foreach 遍历,不得并发调用。
- 内部并行度由 dotnet publish 上的 /m:1 控制,强制单线程 MSBuild;两次构建会话之间应运行
dotnet build-server shutdown并结束 VBCSCompiler。 - 文件锁成因包括:VBCSCompiler 缓存程序集、并行构建同时写同一 DLL、正在运行的 XerahS 实例(Watch Folder 守护进程从 Debug 文件夹加载 DLL)、Avalonia 设计器可能持有已编译 DLL 的引用。
- 关键构建参数:
-p:UseSharedCompilation=false禁用 VBCSCompiler;-p:nodeReuse=false阻止 MSBuild 复用构建节点;/m:1强制单线程;-p:SkipBundlePlugins=true避免自定义 MSBuild 目标路径解析缺陷。 - 错误处理:看到 CS2012 不必惊慌,构建可能仍会成功;始终检查 XerahS.exe 是否生成;ShareX.ImageEditor 是常见问题源;ARM64 更易发生锁定,因为它在 x64 之后运行,可能残留进程。
- 最佳实践:先执行准备阶段清理;监控构建输出中的 "file may be locked by" 消息;检查实际文件生成而非只看退出码;构建期间保持 VBCSCompiler 被结束;构建前关闭正在运行的 XerahS 实例。
- 成功标准:win-x64 与 win-arm64 两个 .exe 安装程序均已生成、大小约 55-60MB、时间戳为本次构建会话、无残留构建进程、dist 文件夹包含预期安装程序。
- 排查:"XerahS.exe" 不存在(Inno Setup)说明主程序未发布,检查更早的构建错误;CS2012 文件锁则结束 VBCSCompiler、删除 obj 文件夹并用 /m:1 重建;安装程序时间戳过旧说明构建静默失败,检查 iscc_log_win-{arch}.txt 日志;只有 x64 成功、ARM64 失败时使用手动 ARM64 构建流程;全部失败则清理解决方案、重启终端并确保没有 XerahS 实例运行。
- 相关文件:共享护栏 build-common;构建脚本 build\windows\package-windows.ps1;Inno Setup 脚本 build\windows\XerahS-setup.iss;版本配置 Directory.Build.props;构建日志 build/windows/iscc_log_win-{arch}.txt。