#msbuild #msbuild-task
Вопрос:
Я пытаюсь создать msbuild csproj, в котором я могу вызывать dotnet run myproject
и удалять папки bin/obj после выполнения. Однако CustomAfterRun
цель (ниже) не выполняется после выполнения цели.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<EnableDefaultItems>false</EnableDefaultItems>
</PropertyGroup>
<ItemGroup>
<Compile Include="Program.cs" />
</ItemGroup>
<Target Name="CustomAfterRun" AfterTargets="Run">
<Message Importance="high" Text="[msbuild] Cleaning bin and obj..."/>
<RemoveDir Directories="$(TargetDir)" />
<RemoveDir Directories="$(ProjectDir)$(BaseIntermediateOutputPath)" />
</Target>
</Project>
Если я создаю цель CustomAfterBuild
(с AfterTargets="Build"
помощью ), она работает нормально (она выполняется после сборки при запуске dotnet build myproj
).
Это ошибка или я делаю что-то не так?
И самая сумасшедшая часть: если внутри CustomAfterBuild
я вызываю <CallTarget Targets="Run" />
, то после сборки вызывается моя программа, и в этом случае CustomAfterRun
она работает нормально !! Недостатком этого метода является то, что вывод программы виден только в том случае, если я включаю уровень детализации, а также после CustomAfterRun
запуска (удаление папок bin/obj) он также попытается запустить программу СНОВА (это означает, что цель запуска вызывается ДВАЖДЫ?!) выдает мне ошибку: System.ComponentModel.Win32Exception (2): The system cannot find the file specified.
.
ИЗМЕНИТЬ: В качестве альтернативы я также попытался переопределить цель запуска, но это вообще не сработало:
<Project>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<EnableDefaultItems>false</EnableDefaultItems>
</PropertyGroup>
<ItemGroup>
<Compile Include="Program.cs" />
</ItemGroup>
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
<Target Name="Run" >
<Message Importance="high" Text="[msbuild] overriden..."/>
</Target>
</Project>
Ответ №1:
Оказывается, у меня было неверное предположение о dotnet run
.
- Есть
dotnet msbuild
то, что в основном является фасадом для вызова msbuild.dotnet build
это просто ярлыкdotnet msbuild -restore
, поэтому он восстановит пакеты nuget и построит их (цель по умолчанию).dotnet clean
также вызывает msbuild (чистая цель). - В аналогичном смысле я ожидал
dotnet run
использоватьRun
цель из msbuild, однако это НЕ так. Он вызываетdotnet msbuild
(при необходимости), но будет запускать выходные данные БЕЗ использования msbuild.
Если я запущуmsbuild -target:Run
события после запуска, они будут работать нормально!
Таким образом, одним из возможных решений было бы использовать обычный msbuild.
Например: dotnet msbuild /t:Restore;Build;Run;Clean MyProj.csproj
),
Однако еще одно поведение, которое меня раздражало, заключается в том, что при запуске программы через msbuild я не получаю цвета (если таковые имеются) в выводе консоли. Вероятно, это связано с тем, что msbuild использует перенаправление консоли для запуска моей программы. dotnet run
к счастью, такого поведения нет, поэтому моим окончательным решением будет:
dotnet run amp; dotnet clean
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<EnableDefaultItems>false</EnableDefaultItems>
</PropertyGroup>
<ItemGroup>
<Compile Include="Program.cs" />
</ItemGroup>
<!-- Clean is not so perfect, clear leftovers -->
<Target Name="CleanBinObj" AfterTargets="Clean">
<RemoveDir Directories="$(ProjectDir)$(BaseOutputPath)" />
<RemoveDir Directories="$(ProjectDir)$(BaseIntermediateOutputPath)" />
</Target>
<!-- If someone uses msbuild to launch, force a clean.. -->
<Target Name="CustomAfterRun" AfterTargets="Run">
<CallTarget Targets="Clean" />
</Target>
</Project>
Или для моего конкретного случая, когда я буду хранить несколько отдельных программ cs в одной папке (каждая со своим собственным csproj), и я хочу переопределить папки bin/obj отдельной (временной) папкой для моего файла:
<Project>
<PropertyGroup>
<TempDir>$(MSBuildProjectName).cs.tmp</TempDir>
<BaseOutputPath>$(TempDir)</BaseOutputPath>
<BaseIntermediateOutputPath>$(TempDir)</BaseIntermediateOutputPath>
</PropertyGroup>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<EnableDefaultItems>false</EnableDefaultItems>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
<!-- Clean is not so perfect, clear leftovers -->
<Target Name="CleanBinObj" AfterTargets="Clean">
<Message Importance="high" Text="Cleaning $(TempDir) (bin/obj)..."/>
<RemoveDir Directories="$(TempDir)" />
</Target>
<!-- If someone uses msbuild to launch, force a clean.. -->
<Target Name="CustomAfterRun" AfterTargets="Run">
<CallTarget Targets="Clean" />
</Target>
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
</Project>