.NET Core 2.1:如何在Visual Studio 2017中进行调试期间触发在项目文件中定义的复制任务?

时间:2018-10-06 16:27:41

标签: msbuild .net-core

有些文件位于其他目录中,我想在构建和发布之前自动复制到项目文件夹中。

经过一些研究和实验,我得出了以下.csproj文件。

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

  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <RuntimeFrameworkVersion>2.1.4</RuntimeFrameworkVersion>
    <TieredCompilation>true</TieredCompilation>
    <PreserveCompilationContext>true</PreserveCompilationContext>
  </PropertyGroup>

  <ItemGroup>
    <APIDefinition Include="D:\SomePlace\*.API.*.yaml" />
  </ItemGroup>

  <Target Name="CopyFiles" BeforeTargets="Compile;Build;Publish">
    <Copy SourceFiles="@(APIDefinition)" DestinationFolder="wwwroot" />
    <Copy SourceFiles="D:\SomePlaceElse\BaseAPISettings.json" DestinationFolder="$(MSBuildProjectDirectory)" />
  </Target>

  <ItemGroup>
    <Compile Remove="wwwroot\**\*;node_modules;bower_components" />
    <None Update="**.user;**.vspscc">
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.4" />
  </ItemGroup>

</Project>

在这里,我定义了CopyFiles目标,该目标应该在放置目标之前运行。此目标使用复制任务将YAML格式的API定义文件和基本API设置复制到项目目录。

这在构建,发布等过程中效果很好。此外,如果我在IDE中删除本地文件,它会立即从源文件中将其重新复制。

有时我会在调试会话之间对这些文件进行更改。然后,当我从Visual Studio开始调试时,由于项目文件没有更改,因此显然已运行的项目正在运行。

由于未构建项目,因此不会触发我的复制任务,并且最终在调试过程中生成陈旧的文件。

在IDE中执行“开始调试F5”时,无论项目的构建状态如何,是否都可以触发我的复制任务?

P.S。 :如果使用Visual Studio 2017 15.8.5和.NET Core 2.1.4运行时有所不同,则使用它。

1 个答案:

答案 0 :(得分:5)

为了完全集成到Visual Studio中项目系统的最新检查中,我建议进行以下更改:

  1. 使项目的源路径和目标路径先前已知
  2. 将它们注册到最新的检查系统。 (还需要黑客以确保重新编译项目源代码,以便输出具有新的时间戳)。
  3. 使MSBuild目标本身成为增量。当不需要复制文件时,这也有助于命令行构建。

完整的更改如下:

<ItemGroup>
  <CustomCopyFile Include="..\TestFiles\*.API.*.yaml"
                  TargetPath="wwwroot\%(Filename)%(Extension)" />
  <CustomCopyFile Include="..\TestFiles\BaseAPISettings.json"
                  TargetPath="%(Filename)%(Extension)" />
  <UpToDateCheckInput Include="@(CustomCopyFile)" />
  <UpToDateCheckBuild Include="@(CustomCopyFile->'%(TargetPath)')"
                      Original="@(CustomCopyFile)" />
  <CustomAdditionalCompileInputs Include="@(CustomCopyFile->'%(TargetPath)')" />
</ItemGroup>

<Target Name="CopyFiles" 
        BeforeTargets="BeforeBuild;BeforePublish"
        Inputs="@(CustomCopyFile)" 
        Outputs="@(CustomCopyFile->'%(TargetPath)')">
  <Copy SourceFiles="@(CustomCopyFile)"
        DestinationFiles="@(CustomCopyFile->'%(TargetPath)')" />
</Target>

CustomCopyFile现在收集所有源文件,并将我们期望的目标文件名放入TargetPath元数据中。

UpToDateCheckInput项目告诉Visual Studio如果这些项目之一发生更改,则重建项目。

UpToDateCheckBuild项目指示Visual Studio仅对照特殊源项目检查这些项目。这对于此示例项目是多余的,但如果目标路径不在项目目录中,而是在某些中间输出(obj ..)文件夹中,并且没有重新评估将看到这些新文件,则可能会有所帮助。如果在处理过程中还修改了文件(例如替换文件中的变量),也会很有帮助。

CustomAdditionalCompileInputs是这里的黑客,因为项目已复制到项目文件夹,并被视为自动“输入到输出”。因此,如果源文件发生更改,我们将强制重新编译项目。如果我们不这样做,则在更改源yaml文件后,它将永远不会考虑该项目是最新的,因为它们比已编译的app.dll文件要新。