Как я могу использовать объекты BeforeBuild и AfterBuild с помощью Visual Studio 2017?

После перехода на csproj для использования Visual Studio 2017 и Microsoft.NET.Sdk мои целевые объекты "BeforeBuild" и "AfterBuild" больше не работают. Мой файл выглядит следующим образом:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net46</TargetFramework>
  </PropertyGroup>

  <!-- my targets that don't run -->
  <Target Name="BeforeBuild">
      <Message Text="Should run before build" Importance="High" />
  </Target>

  <Target Name="AfterBuild">
      <Message Text="Should run after build" Importance="High" />
  </Target>

</Project>

Ответ 1

Связанная с этим проблема с MSBuild git рекомендует не использовать BeforeBuild/AfterBuild в качестве имен задач в будущем, вместо этого присваивать имя задаче соответствующим образом и связывать ее с целями

<Project Sdk="Microsoft.NET.Sdk"> 
  <PropertyGroup>
    <TargetFramework>net46</TargetFramework>
  </PropertyGroup>

  <!-- Instead of BeforeBuild target -->
  <Target Name="MyCustomTask" BeforeTargets="CoreBuild" >
      <Message Text="Should run before build" Importance="High" />
  </Target>

  <!-- Replaces AfterBuild target -->
  <Target Name="AnotherCustomTarget" AfterTargets="CoreCompile">
      <Message Text="Should run after build" Importance="High" />
  </Target>    
</Project>

Это дает вам файл проекта idiomatic VS 2017, но какие цели вы активируете до/после, все еще остается предметом споров в настоящее время.

Ответ 2

Когда вы указываете Project Sdk="Microsoft.NET.Sdk", вы используете "имплицированный верхний и нижний импорт". Это означает, что есть невидимый импорт в Microsoft.NET.Sdk/Sdk.targets в нижней части вашего файла csproj, который переопределяет цели "BeforeBuild" и "AfterBuild".

Вы можете исправить это, используя явные импорт, чтобы вы могли контролировать порядок импорта.

<Project>

  <Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />

  <PropertyGroup>
    <TargetFramework>net46</TargetFramework>
  </PropertyGroup>

  <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />

  <!-- add your custom targets after Sdk.targets is imported -->
  <Target Name="BeforeBuild">
      <Message Text="Should run before build" Importance="High" />
  </Target>

  <Target Name="AfterBuild">
      <Message Text="Should run after build" Importance="High" />
  </Target>

</Project>

Ответ 3

В уже упомянутом выпуске GitHub Rainer Sigwald предлагает гораздо более короткое и элегантное решение:

<Target Name="CustomBeforeBuild" BeforeTargets="BeforeBuild"> ... </Target>
<Target Name="CustomAfterBuild" AfterTargets="AfterBuild"> ... </Target>

Выглядит странно, но работает отлично.