build-windows-exe
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseYou are an expert Windows build automation specialist for .NET projects.
Follow these instructions exactly and in order to build Windows executables for XerahS while avoiding common file locking issues.
<task>
<goal>Build Windows installers for both x64 and ARM64 architectures.</goal>
<goal>Handle file locking issues that commonly occur during compilation.</goal>
<goal>Ensure Inno Setup successfully creates installer executables.</goal>
<goal>Validate that the build artifacts exist and are recent.</goal>
</task>
<context>
<build_script_path>ShareX Team\XerahS\build\windows\package-windows.ps1</build_script_path>
<dist_output_path>ShareX Team\XerahS\dist</dist_output_path>
<common_locked_file>ShareX Team\XerahS\ImageEditor\src\ShareX.ImageEditor\obj\Release\net10.0-windows10.0.26100.0\ShareX.ImageEditor.dll</common_locked_file>
<expected_outputs>
- XerahS-{version}-win-x64.exe
- XerahS-{version}-win-arm64.exe
</expected_outputs>
</context>您是一位专注于.NET项目的Windows构建自动化专家。
请严格按照以下说明的顺序执行,为XerahS构建Windows可执行文件,同时避免常见的文件锁定问题。
<task>
<goal>为x64和ARM64架构构建Windows安装程序。</goal>
<goal>处理编译过程中常见的文件锁定问题。</goal>
<goal>确保Inno Setup成功创建安装程序可执行文件。</goal>
<goal>验证构建产物是否存在且为最新版本。</goal>
</task>
<context>
<build_script_path>ShareX Team\XerahS\build\windows\package-windows.ps1</build_script_path>
<dist_output_path>ShareX Team\XerahS\dist</dist_output_path>
<common_locked_file>ShareX Team\XerahS\ImageEditor\src\ShareX.ImageEditor\obj\Release\net10.0-windows10.0.26100.0\ShareX.ImageEditor.dll</common_locked_file>
<expected_outputs>
- XerahS-{version}-win-x64.exe
- XerahS-{version}-win-arm64.exe
</expected_outputs>
</context>Build Process
构建流程
Phase 0: Update ImageEditor Submodule
阶段0:更新ImageEditor子模块
Always pull the latest ImageEditor submodule before building to ensure the embedded image editor is up-to-date.
powershell
cd 'ShareX Team\XerahS'
git submodule update --remote --merge ImageEditor构建前务必拉取ImageEditor子模块的最新版本,以确保嵌入式图像编辑器是最新的。
powershell
cd 'ShareX Team\XerahS'
git submodule update --remote --merge ImageEditorPhase 1: Pre-Build Cleanup
阶段1:构建前清理
CRITICAL: File locking is the #1 cause of Windows build failures. Always clean before building.
-
Kill all potential file-locking processes:powershell
Get-Process | Where-Object { $_.Name -like '*XerahS*' -or $_.Name -like '*dotnet*' -or $_.Name -like '*MSBuild*' -or $_.Name -like '*VBCSCompiler*' } | Stop-Process -Force -ErrorAction SilentlyContinue -
Clean the solution:powershell
cd 'ShareX Team\XerahS' dotnet clean src/desktop/XerahS.sln --nologo -c Release -
If file locks persist, delete the problematic obj folder:powershell
Remove-Item 'ShareX Team\XerahS\ImageEditor\src\ShareX.ImageEditor\obj' -Recurse -Force -ErrorAction SilentlyContinue
关键提示:文件锁定是Windows构建失败的首要原因。构建前务必执行清理操作。
-
终止所有可能导致文件锁定的进程:powershell
Get-Process | Where-Object { $_.Name -like '*XerahS*' -or $_.Name -like '*dotnet*' -or $_.Name -like '*MSBuild*' -or $_.Name -like '*VBCSCompiler*' } | Stop-Process -Force -ErrorAction SilentlyContinue -
清理解决方案:powershell
cd 'ShareX Team\XerahS' dotnet clean src/desktop/XerahS.sln --nologo -c Release -
如果文件锁仍然存在,删除有问题的obj文件夹:powershell
Remove-Item 'ShareX Team\XerahS\ImageEditor\src\ShareX.ImageEditor\obj' -Recurse -Force -ErrorAction SilentlyContinue
Phase 2: Initial Build Attempt
阶段2:首次构建尝试
-
Run the packaging script:powershell
cd 'ShareX Team\XerahS\build\windows' .\package-windows.ps1 -
Check for successful completion:
- Script should complete with exit code 0
- Both installers should be created in the folder
dist
-
运行打包脚本:powershell
cd 'ShareX Team\XerahS\build\windows' .\package-windows.ps1 -
检查构建是否成功完成:
- 脚本应返回退出码0
- 两个安装程序应在文件夹中创建
dist
Phase 3: Handle File Lock Failures
阶段3:处理文件锁定失败
If you see errors like:
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'
Then apply these fixes:
-
Kill compiler processes again:powershell
Get-Process | Where-Object { $_.Name -like '*VBCSCompiler*' -or $_.Name -like '*dotnet*' -or $_.Name -like '*csc*' } | Stop-Process -Force -ErrorAction SilentlyContinue Start-Sleep -Seconds 2 -
Remove the locked obj folder:powershell
Remove-Item 'ShareX Team\XerahS\ImageEditor\src\ShareX.ImageEditor\obj\Release' -Recurse -Force -ErrorAction SilentlyContinue -
Pre-build the ImageEditor project separately with single-threaded compilation:powershell
dotnet build 'ShareX Team\XerahS\ImageEditor\src\ShareX.ImageEditor\ShareX.ImageEditor.csproj' -c Release -p:UseSharedCompilation=false /m:1- The flag forces single-threaded build
/m:1 - disables the VBCSCompiler server
UseSharedCompilation=false
- The
-
Re-run the packaging script:powershell
cd 'ShareX Team\XerahS\build\windows' .\package-windows.ps1
如果出现以下错误:
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'
请应用以下修复方案:
-
再次终止编译器进程:powershell
Get-Process | Where-Object { $_.Name -like '*VBCSCompiler*' -or $_.Name -like '*dotnet*' -or $_.Name -like '*csc*' } | Stop-Process -Force -ErrorAction SilentlyContinue Start-Sleep -Seconds 2 -
删除被锁定的obj文件夹:powershell
Remove-Item 'ShareX Team\XerahS\ImageEditor\src\ShareX.ImageEditor\obj\Release' -Recurse -Force -ErrorAction SilentlyContinue -
单独预构建ImageEditor项目,使用单线程编译:powershell
dotnet build 'ShareX Team\XerahS\ImageEditor\src\ShareX.ImageEditor\ShareX.ImageEditor.csproj' -c Release -p:UseSharedCompilation=false /m:1- 参数强制使用单线程构建
/m:1 - 禁用VBCSCompiler服务器
UseSharedCompilation=false
-
重新运行打包脚本:powershell
cd 'ShareX Team\XerahS\build\windows' .\package-windows.ps1
Phase 4: Fallback - Manual ARM64 Build
阶段4:备选方案 - 手动构建ARM64版本
If ARM64 continues to fail but x64 succeeds, build ARM64 manually:
-
Clean and kill processes:powershell
Get-Process | Where-Object { $_.Name -like '*VBCSCompiler*' -or $_.Name -like '*dotnet*' } | Stop-Process -Force -ErrorAction SilentlyContinue Remove-Item 'ShareX Team\XerahS\ImageEditor\src\ShareX.ImageEditor\obj\Release' -Recurse -Force -ErrorAction SilentlyContinue -
Pre-build ImageEditor:powershell
dotnet build 'ShareX Team\XerahS\ImageEditor\src\ShareX.ImageEditor\ShareX.ImageEditor.csproj' -c Release -p:UseSharedCompilation=false /m:1 -
Publish ARM64 manually:powershell
$root = 'ShareX Team\XerahS' $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 -
Publish plugins:powershell
$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" } -
Run Inno Setup manually:powershell
$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
如果ARM64构建持续失败但x64构建成功,请手动构建ARM64版本:
-
清理并终止进程:powershell
Get-Process | Where-Object { $_.Name -like '*VBCSCompiler*' -or $_.Name -like '*dotnet*' } | Stop-Process -Force -ErrorAction SilentlyContinue Remove-Item 'ShareX Team\XerahS\ImageEditor\src\ShareX.ImageEditor\obj\Release' -Recurse -Force -ErrorAction SilentlyContinue -
预构建ImageEditor:powershell
dotnet build 'ShareX Team\XerahS\ImageEditor\src\ShareX.ImageEditor\ShareX.ImageEditor.csproj' -c Release -p:UseSharedCompilation=false /m:1 -
手动发布ARM64版本:powershell
$root = 'ShareX Team\XerahS' $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 -
发布插件:powershell
$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:powershell
$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
Phase 5: Validation
阶段5:验证
-
Check that both installers exist:powershell
Get-ChildItem 'ShareX Team\XerahS\dist' -Filter '*.exe' | Select-Object Name, Length, LastWriteTime | Format-Table -AutoSize -
Verify they were created recently (within the last few minutes)
-
Expected output:
Name Length LastWriteTime ---- ------ ------------- XerahS-{version}-win-arm64.exe ~55-60MB [Today's date] XerahS-{version}-win-x64.exe ~55-60MB [Today's date]
-
检查两个安装程序是否存在:powershell
Get-ChildItem 'ShareX Team\XerahS\dist' -Filter '*.exe' | Select-Object Name, Length, LastWriteTime | Format-Table -AutoSize -
验证文件是否为近期创建(过去几分钟内)
-
预期输出:
Name Length LastWriteTime ---- ------ ------------- XerahS-{version}-win-arm64.exe ~55-60MB [当前日期] XerahS-{version}-win-x64.exe ~55-60MB [当前日期]
Important Notes
重要说明
Sequential Builds Are Mandatory
必须按顺序构建
NEVER run two builds at the same time. ImageEditor targets multiple TFMs (, , , ) and MSBuild parallelism causes all of them to race on the same output path, producing file lock errors.
net9.0net10.0net9.0-windows10.0.26100.0net10.0-windows10.0.26100.0ShareX.ImageEditor.dllCS2012- Architectures: already iterates
package-windows.ps1thenwin-x64sequentially viawin-arm64— never invoke it twice concurrently.foreach - Internal parallelism: Controlled by on the
/m:1call, which forces single-threaded MSBuild and eliminates the intra-build race.dotnet publish - Between builds: Always run and kill VBCSCompiler between consecutive build sessions.
dotnet build-server shutdown
切勿同时运行两个构建任务。ImageEditor针对多个TFM(、、、)进行构建,MSBuild的并行处理会导致它们争夺同一个输出路径,从而产生文件锁定错误。
net9.0net10.0net9.0-windows10.0.26100.0net10.0-windows10.0.26100.0ShareX.ImageEditor.dllCS2012- 架构顺序:已通过
package-windows.ps1循环按顺序执行foreach和win-x64构建——切勿同时调用该脚本两次。win-arm64 - 内部并行处理:由调用的
dotnet publish参数控制,强制使用单线程MSBuild,消除构建内部的资源竞争。/m:1 - 构建间隔:在连续的构建会话之间,务必运行并终止VBCSCompiler进程。
dotnet build-server shutdown
Why File Locking Happens
文件锁定的原因
- VBCSCompiler: Roslyn compiler server caches assemblies for faster builds
- Parallel builds: Multiple projects trying to write the same DLL simultaneously
- Running XerahS instances: The Watch Folder daemon loads DLLs from Debug folder
- Avalonia designer: May hold references to compiled DLLs
- VBCSCompiler:Roslyn编译器服务器会缓存程序集以加快构建速度
- 并行构建:多个项目尝试同时写入同一个DLL文件
- 运行中的XerahS实例:监视文件夹守护进程会从Debug文件夹加载DLL
- Avalonia设计器:可能会保留已编译DLL的引用
Key Build Parameters
关键构建参数
- : Disables VBCSCompiler server
-p:UseSharedCompilation=false - : Prevents MSBuild from reusing build nodes
-p:nodeReuse=false - : Forces single-threaded build (slower but no race conditions)
/m:1 - : Avoids custom MSBuild target path resolution bugs
-p:SkipBundlePlugins=true
- :禁用VBCSCompiler服务器
-p:UseSharedCompilation=false - :防止MSBuild重复使用构建节点
-p:nodeReuse=false - :强制单线程构建(速度较慢但无资源竞争)
/m:1 - :避免自定义MSBuild目标路径解析错误
-p:SkipBundlePlugins=true
Build Error Handling
构建错误处理
- Don't panic if you see CS2012 errors: The build may still succeed
- Always check if XerahS.exe was created: The error might be during a retry
- ImageEditor is the usual culprit: It has parallel TFM builds (net9.0, net10.0, with/without Windows SDK)
- ARM64 builds are more prone to locking: They run after x64 which may leave processes
- 遇到CS2012错误无需惊慌:构建仍可能成功
- 始终检查XerahS.exe是否已创建:错误可能出现在重试过程中
- ImageEditor通常是问题根源:它存在并行TFM构建(net9.0、net10.0,带/不带Windows SDK)
- ARM64构建更容易出现锁定问题:它在x64构建之后运行,x64构建可能会残留进程
Best Practices
最佳实践
- Always run Phase 1 cleanup first
- Monitor the build output for "file may be locked by" messages
- Check actual file creation, not just exit codes
- Keep VBCSCompiler killed during builds
- Close any running XerahS instances before building
- 始终先执行阶段1的清理操作
- 监视构建输出中的“file may be locked by”消息
- 检查实际文件是否创建,而不仅仅是退出码
- 构建过程中始终保持VBCSCompiler进程被终止
- 构建前关闭所有运行中的XerahS实例
Success Criteria
成功标准
- ✅ Both win-x64 and win-arm64 .exe installers created
- ✅ Files are ~55-60 MB in size
- ✅ Timestamps are recent (within build session)
- ✅ No lingering build processes (VBCSCompiler, dotnet, MSBuild)
- ✅ Dist folder contains the expected installer files
- ✅ 已创建win-x64和win-arm64的.exe安装程序
- ✅ 文件大小约为55-60 MB
- ✅ 时间戳为近期(构建会话期间)
- ✅ 无残留的构建进程(VBCSCompiler、dotnet、MSBuild)
- ✅ Dist文件夹包含预期的安装程序文件
Troubleshooting
故障排除
| Symptom | Solution |
|---|---|
| "XerahS.exe" does not exist (Inno Setup) | The main app didn't publish; check for earlier build errors |
| CS2012 file lock error | Kill VBCSCompiler, delete obj folder, rebuild with |
| Installer created but old timestamp | Build failed silently; check logs in |
| Only x64 succeeds, ARM64 fails | Use Phase 4 manual ARM64 build process |
| All builds fail | Clean solution, restart terminal, ensure no XerahS instances running |
| 症状 | 解决方案 |
|---|---|
| “XerahS.exe”不存在(Inno Setup报错) | 主应用未发布;检查早期的构建错误 |
| CS2012文件锁定错误 | 终止VBCSCompiler进程,删除obj文件夹,使用 |
| 安装程序已创建但时间戳为旧版本 | 构建静默失败;检查 |
| 仅x64构建成功,ARM64构建失败 | 使用阶段4的手动ARM64构建流程 |
| 所有构建均失败 | 清理解决方案,重启终端,确保无运行中的XerahS实例 |
Related Files
相关文件
- Build script: build\windows\package-windows.ps1
- Inno Setup script: build\windows\XerahS-setup.iss
- Version config: Directory.Build.props
- Build logs:
build/windows/iscc_log_win-{arch}.txt
- 构建脚本:build\windows\package-windows.ps1
- Inno Setup脚本:build\windows\XerahS-setup.iss
- 版本配置:Directory.Build.props
- 构建日志:
build/windows/iscc_log_win-{arch}.txt