You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将工具可执行程序作为常规构建的一部分发布?

解决入口项目嵌入工具项目发布产物的问题

我需要将EntryPoint.Diagnostics.Utility项目构建为独立可执行程序,并嵌入到入口项目EntryPoint的输出目录中,最终输出结构要求如下:

EntryPoint/bin/Debug/net10.0-windows/
    Diagnostics.Utility/
        Diagnostics.Utility.exe
        Diagnostics.Utility.dll
        ...

当前实现的问题

之前用Exec调用dotnet publish的方式存在两个核心问题:

  • 竞争条件导致构建失败:构建整个解决方案时,部分机器会出现文件找不到的错误,示例报错如下:
[...]
Restored C:\buildagent\work\9eb378ffe858f165\src\1-0 Spectroscopy\5-BootStrapper\EntryPoint\EntryPoint.csproj (in 12.46 sec).
Publishing into 'obj\Release\net10.0-windows\win-x64\DiagnosticsUtility-publish'
  Determining projects to restore...
  Restored C:\buildagent\work\9eb378ffe858f165\src\1-0 Spectroscopy\3-ApplicationService\Diagnostics\Spectroscopy.ApplicationService.Diagnostics.Contract\Spectroscopy.ApplicationService.Diagnostics.Contract.csproj (in 333 ms).
  Restored C:\buildagent\work\9eb378ffe858f165\src\1-0 Spectroscopy\5-BootStrapper\EntryPoint.Diagnostics.Utility\EntryPoint.Diagnostics.Utility.csproj (in 801 ms).
C:\Program Files\dotnet\sdk\10.0.101\Microsoft.Common.CurrentVersion.targets(4903,5): error MSB3030: Could not copy the file "C:\buildagent\work\9eb378ffe858f165\src\1-0 Spectroscopy\5-BootStrapper\EntryPoint\obj\Release\net10.0-windows\win-x64\DiagnosticsUtility-artifacts\obj\Spectroscopy.ApplicationService.Diagnostics.Contract\release\AntonPaar.Orca.Spec.ApplicationService.Diagnostics.Contract.dll" because it was not found. [C:\buildagent\work\9eb378ffe858f165\src\1-0 Spectroscopy\3-ApplicationService\Diagnostics\Spectroscopy.ApplicationService.Diagnostics.Contract\Spectroscopy.ApplicationService.Diagnostics.Contract.csproj] [C:\buildagent\work\9eb378ffe858f165\src\1-0 Spectroscopy\5-BootStrapper\EntryPoint\EntryPoint.csproj]
C:\buildagent\work\9eb378ffe858f165\src\1-0 Spectroscopy\5-BootStrapper\EntryPoint\EntryPoint.csproj(31,9): error MSB3073: The command "dotnet publish ^
C:\buildagent\work\9eb378ffe858f165\src\1-0 Spectroscopy\5-BootStrapper\EntryPoint\EntryPoint.csproj(31,9): error MSB3073:             "..\EntryPoint.Diagnostics.Utility\EntryPoint.Diagnostics.Utility.csproj" ^
C:\buildagent\work\9eb378ffe858f165\src\1-0 Spectroscopy\5-BootStrapper\EntryPoint\EntryPoint.csproj(31,9): error MSB3073:             --artifacts-path "obj\Release\net10.0-windows\win-x64\DiagnosticsUtility-artifacts" ^
C:\buildagent\work\9eb378ffe858f165\src\1-0 Spectroscopy\5-BootStrapper\EntryPoint\EntryPoint.csproj(31,9): error MSB3073:             --output "obj\Release\net10.0-windows\win-x64\DiagnosticsUtility-publish" ^
C:\buildagent\work\9eb378ffe858f165\src\1-0 Spectroscopy\5-BootStrapper\EntryPoint\EntryPoint.csproj(31,9): error MSB3073:             --self-contained false ^
C:\buildagent\work\9eb378ffe858f165\src\1-0 Spectroscopy\5-BootStrapper\EntryPoint\EntryPoint.csproj(31,9): error MSB3073:             --configuration Release ^
C:\buildagent\work\9eb378ffe858f165\src\1-0 Spectroscopy\5-BootStrapper\EntryPoint\EntryPoint.csproj(31,9): error MSB3073:             --runtime win-x64" exited with code 1.
  • 无增量构建支持:工具项目的源文件变更后,不会自动触发重建,必须手动清理后重新构建。

正确的MSBuild实现方案

替换原有的Exec任务,使用MSBuild内置任务处理项目发布,同时配置增量构建和路径隔离:

<Target Name="PublishDiagnosticsUtility" 
        BeforeTargets="BeforeBuild"
        Inputs="..\EntryPoint.Diagnostics.Utility\**\*.cs;..\EntryPoint.Diagnostics.Utility\EntryPoint.Diagnostics.Utility.csproj"
        Outputs="$(IntermediateOutputPath)DiagnosticsUtility-publish\Diagnostics.Utility.exe">

    <MSBuild Projects="..\EntryPoint.Diagnostics.Utility\EntryPoint.Diagnostics.Utility.csproj"
             Targets="Publish"
             Properties="Configuration=$(Configuration);
                         RuntimeIdentifier=win-x64;
                         SelfContained=false;
                         PublishDir=$(IntermediateOutputPath)DiagnosticsUtility-publish;
                         UseArtifactsOutput=true;
                         ArtifactsPath=$(IntermediateOutputPath)DiagnosticsUtility-artifacts;
                         BuildProjectReferences=true"
             BuildInParallel="false" />

    <ItemGroup>
        <_DiagnosticsUtilityPublishFiles Include="$(IntermediateOutputPath)DiagnosticsUtility-publish\**" />
        <Content Include="@(_DiagnosticsUtilityPublishFiles)"
                 Link="Diagnostics.Utility\%(RecursiveDir)%(Filename)%(Extension)"
                 PackagePath="content\Diagnostics.Utility\%(RecursiveDir)%(Filename)%(Extension)"
                 CopyToOutputDirectory="PreserveNewest" />
    </ItemGroup>
</Target>

方案说明

  1. 增量构建支持:通过Inputs和Outputs定义目标的输入输出,MSBuild会自动检测工具项目的源文件或项目文件变更,触发重新发布,无需手动清理。
  2. 解决竞争条件:
    • 设置BuildInParallel="false",确保工具项目发布任务与解决方案其他构建任务串行执行,避免文件访问冲突。
    • 使用独立的ArtifactsPath和PublishDir,完全隔离工具项目的中间输出和发布产物,不与解决方案内其他构建共享路径。
  3. 属性传递与环境一致性:将配置、运行时标识符等属性直接传递给MSBuild任务,确保发布产物与入口项目构建环境一致。
  4. 优化复制逻辑:将CopyToOutputDirectory改为PreserveNewest,仅复制更新过的文件,提升构建效率。

内容的提问来源于stack exchange,提问作者user272507

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.01 20:22:26