关于 build-windows-exe
这项 Windows 构建自动化技能用于生成 XerahS 的 x64 和 ARM64 安装程序,说明顺序打包、文件锁恢复步骤及构建产物检查方法。
主要功能
- 01Windows x64 与 ARM64 打包
- 02文件锁恢复流程
- 03ARM64 手动发布备用方案
- 04安装程序产物验证
适用场景
- 01构建两种架构的 Windows 安装程序
- 02排查编译时的文件锁
- 03检查安装程序是否存在及其时间戳
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ sharex/ xerahs --skill build-windows-exe安装后在 Claude Code 中输入/build-windows-exe确认已加载。
详细介绍
你是精通 .NET 项目的 Windows 构建自动化专家。
请严格按照以下说明及顺序操作,为 XerahS 构建 Windows 可执行文件,同时避免常见的文件锁定问题。
为 x64 和 ARM64 架构构建 Windows 安装程序。 处理编译期间常见的文件锁定问题。 确保 Inno Setup 成功创建安装程序可执行文件。 验证构建产物存在且为近期生成。 build\windows\package-windows.ps1 dist ShareX.ImageEditor\src\ShareX.ImageEditor\obj\Release\net10.0-windows10.0.26100.0\ShareX.ImageEditor.dll - XerahS-{version}-win-x64.exe - XerahS-{version}-win-arm64.exe通用构建防护措施
开始 Windows 打包前,请遵循 build-common,了解通用的超时、锁恢复、禁止并行构建、-m:1、TFM 和 SkiaSharp 规则。此 Windows 技能负责 Windows 打包命令、Inno Setup 行为和 Windows 构建产物验证。
构建流程
准备工作
构建固定的子模块修订版本。只有在任务要求时,才使用操作者的 Git 包装程序更新 ImageEditor。
检查是否有其他构建正在使用这些输出。如果发生锁定,请遵循 build-common,找出由当前任务持有的锁,并仅清理受影响的输出。常规打包无需终止所有进程或执行全面清理。
阶段 2:首次尝试构建
-
运行打包脚本:
.\build\windows\package-windows.ps1 -
检查是否成功完成:
- 脚本应以退出代码 0 完成
dist文件夹中应生成两个安装程序
阶段 3:处理文件锁定故障
如果出现以下错误:
CS2012: Cannot open '...ShareX.ImageEditor.dll' for writingThe process cannot access the file ... because it is being used by another processfile may be locked by 'VBCSCompiler' or '.NET Host' or 'csc'
请采取以下修复措施:
-
遵循 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 服务器
-
重新运行打包脚本:
.\build\windows\package-windows.ps1
阶段 4:回退方案——手动构建 ARM64
如果 ARM64 仍然失败,但 x64 成功,请手动构建 ARM64:
-
使用 build-common 恢复已确认的锁定。
-
预构建
ShareX.ImageEditor:dotnet build 'ShareX.ImageEditor\src\ShareX.ImageEditor\ShareX.ImageEditor.csproj' -c Release -p:UseSharedCompilation=false /m:1 -
手动发布 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
阶段 5:验证
-
检查两个安装程序是否存在:
Get-ChildItem 'dist' -Filter '*.exe' | Select-Object Name, Length, LastWriteTime | Format-Table -AutoSize -
确认它们是近期创建的(在最近几分钟内)
-
预期输出:
Name Length LastWriteTime ---- ------ ------------- XerahS-{version}-win-arm64.exe ~55-60MB [Today's date] XerahS-{version}-win-x64.exe ~55-60MB [Today's date]
重要说明
必须按顺序构建
绝不能同时运行两个构建。 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已通过foreach依次处理win-x64和win-arm64——绝不要并发调用两次。 - 内部并行处理:由
dotnet publish调用中的/m:1控制,它会强制 MSBuild 单线程运行并消除构建内部的竞争。 - 构建之间:连续的构建会话之间,始终运行
dotnet build-server shutdown并终止 VBCSCompiler。
文件锁定的原因
- VBCSCompiler:Roslyn 编译器服务器会缓存程序集,以加快构建速度
- 并行构建:多个项目同时尝试写入同一个 DLL
- 正在运行的 XerahS 实例:监视文件夹守护进程会从 Debug 文件夹加载 DLL
- Avalonia 设计器:可能会持有对已编译 DLL 的引用
关键构建参数
-p:UseSharedCompilation=false:禁用 VBCSCompiler 服务器-p:nodeReuse=false:防止 MSBuild 重用构建节点/m:1:强制单线程构建(速度较慢,但不会发生竞争条件)-p:SkipBundlePlugins=true:避免自定义 MSBuild 目标路径解析错误
构建错误处理
- 看到 CS2012 错误时不要慌:构建仍可能成功
- 始终检查是否已创建 XerahS.exe:错误可能发生在重试过程中
ShareX.ImageEditor通常是罪魁祸首:它会并行构建多个 TFM(net9.0、net10.0,以及有无 Windows SDK 的配置)- ARM64 构建更容易发生锁定:它们在 x64 构建之后运行,可能会遗留进程
最佳实践
- 始终先执行 Phase 1 清理
- 监控构建输出,留意“file may be locked by”消息
- 检查文件是否实际创建,而不只是查看退出代码
- 构建期间确保 VBCSCompiler 已终止
- 构建前关闭所有正在运行的 XerahS 实例
成功标准
- ✅ 已创建 win-x64 和 win-arm64 的 .exe 安装程序
- ✅ 文件大小约为 55-60 MB
- ✅ 时间戳较新(在本次构建期间)
- ✅ 没有残留的构建进程(VBCSCompiler、dotnet、MSBuild)
- ✅ Dist 文件夹中包含预期的安装程序文件
故障排除
| 症状 | 解决方案 |
|---|---|
| Inno Setup 提示“XerahS.exe”不存在 | 主应用未能发布;检查之前是否有构建错误 |
| CS2012 文件锁定错误 | 终止 VBCSCompiler,删除 obj 文件夹,然后使用 /m:1 重新构建 |
| 已创建安装程序,但时间戳较旧 | 构建静默失败;检查 iscc_log_win-{arch}.txt 中的日志 |
| 只有 x64 构建成功,ARM64 失败 | 使用 Phase 4 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