如何将实用工具的可执行文件作为常规构建的一部分发布?

编程语言 2026-07-09

我的入口点项目需要将另一个项目构建为一个单独的可执行文件,并将其包含在输出中:

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

目前,我的做法如下:

<Target Name="PublishDiagnosticsUtility">
    <!--
    We need to be careful how we do this, because the project is also part of the solution.
    Without special treatment, it would use the same 'obj' folder which will cause issues.

    My original solution was to override 'IntermediateOutputPath' or 'BaseIntermediateOutputPath'.
    However, this causes issues because it includes all '**/*.cs' files by default.
    Normally it would exclude the 'obj/*.cs' files but if we change the path, they would be included.

    Overriding the artifacts path seems to do exactly what we want, it builds the other project without any interference.

    TODO This does not detect changes in the diagnostics project, a clean rebuild is always required
    TODO This appears to cause race conditions when building the solution, but I don't know why
    -->
    <Exec Command="dotnet publish ^
        &quot;..\EntryPoint.Diagnostics.Utility\EntryPoint.Diagnostics.Utility.csproj&quot; ^
        --artifacts-path &quot;$(IntermediateOutputPath)DiagnosticsUtility-artifacts&quot; ^
        --output &quot;$(IntermediateOutputPath)DiagnosticsUtility-publish&quot; ^
        --self-contained false ^
        --configuration $(Configuration) ^
        --runtime win-x64" />

    <ItemGroup>
        <!--
        For some reason we can't put that into the 'Content' item below.
        If we do, the transforms would evaluate to nothing. -->
        <_DiagnosticsUtilityPublishFiles Include="$(IntermediateOutputPath)DiagnosticsUtility-publish\**" />

        <!-- Include the results in the output -->
        <Content Include="@(_DiagnosticsUtilityPublishFiles)"
                    Link="Diagnostics.Utility\%(RecursiveDir)%(Filename)%(Extension)"
                    PackagePath="content\Diagnostics.Utility\%(RecursiveDir)%(Filename)%(Extension)"
                    CopyToOutputDirectory="Always" />
    </ItemGroup>
</Target>

不幸的是,这段代码存在两个问题:

  1. 我已经在使用独立的产物路径,但在构建整个解决方案时,它似乎仍然会干扰构建过程。这是一个竞争条件,并且只在某些计算机上发生:

none [...] 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. 2.如果源文件有修改,它将不会重新构建该项目。

我以为使用内置的 MSBuild 任务会有帮助,但我不确定如何准确实现,这正是我现在的位置:

<MSBuild
    Projects="..\EntryPoint.Diagnostics.Utility\EntryPoint.Diagnostics.Utility.csproj"
    Targets="Publish"
    Properties="UseArtifactsOutput=True;ArtifactsPath=$(IntermediateOutputPath)DiagnosticsUtility-artifacts;PublishDir=$(IntermediateOutputPath)DiagnosticsUtility-publish"/>

解决方案

看起来我的方法存在多种问题。

第一个问题是,我在发布前没有显式地做还原。我本来不认为这是必要的,但出于某种原因确实需要。所以我必须在对子项目执行 dotnet restore 之后在执行 dotnet publish

第二个问题是,两个项目都对同一个 AntonPaar.Orca.Spec.ApplicationService.Diagnostics.Contract 项目有共享依赖。publish 会先与 --artifacts-path 一起运行,这以某种方式干扰了父项目。

我无法找到这种相互作用的原因,在我看来,使用 --artifacts-pathArtifactsPath 应该足以避免问题,但事实似乎并非如此。

在我的情况下,该项目只有一个源文件被两个项目引用,因此我把它作为变通方法复制了一份。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章