C# 如何在编译开始之前但在生成中间文件之后运行MSBuild任务?

C# 如何在编译开始之前但在生成中间文件之后运行MSBuild任务?,c#,.net,visual-studio,visual-studio-2015,msbuild,C#,.net,Visual Studio,Visual Studio 2015,Msbuild,Background:StyleCop抱怨自动生成的文件格式不好,在我尝试构建项目时导致了许多警告。自动生成的文件位于我的项目的obj/目录中,我想创建一个MSBuild任务,该任务在//之前,并尝试使用BeforeBuild和BeforeCompile 另外,由于我使用的是“new”StyleCop,因此无法将放入项目文件中。参见我设法解决了这个问题;请参阅@stijn的超级有用的评论 首先,我从命令行运行msbuild/v:detailed。这会增加MSBuild的详细程度,从而使您能够更

Background:StyleCop抱怨自动生成的文件格式不好,在我尝试构建项目时导致了许多警告。自动生成的文件位于我的项目的
obj/
目录中,我想创建一个MSBuild任务,该任务在
//之前,并尝试使用
BeforeBuild
BeforeCompile


另外,由于我使用的是“new”StyleCop,因此无法将
放入项目文件中。参见

我设法解决了这个问题;请参阅@stijn的超级有用的评论

  • 首先,我从命令行运行
    msbuild/v:detailed
    。这会增加MSBuild的详细程度,从而使您能够更详细地了解正在进行的操作,例如,您可以看到正在运行的每个目标的名称

  • 我在日志中搜索生成文件的目标的名称。在我的例子中,结果是
    GenerateProgramFiles

  • 我用
    postertargets=“GenerateProgramFiles”
    标记了我的自定义目标,因此它在生成文件后运行


除非sombody熟记所有构建步骤,否则解决方案是在运行构建时将诊断设置为详细(可以在VS中的某个位置进行设置,或者将/v:d传递到命令行),然后查看输出-其中将列出所有目标-并找出生成文件的目标。然后将
postertargets=“
添加到您的MarkGeneratedFiles目标中(无需BeforeComile等)anymore0@stijn非常感谢!我能够找到生成此文件的目标(称为
GenerateProgramFile
),并将
posterTargets=“GenerateProgramFile”
在我的目标中。现在一切都按预期进行了。@ColeWu MSFT当然。我已经发布了我问题的答案,但是我不能再接受我自己的答案6个小时了。
<!-- StyleCop complains about a file that's auto-generated by the designer,
    so we need to prepend 'auto-generated' to it beforehand. -->
<Target Name="BeforeCompile" DependsOnTargets="MarkGeneratedFiles" />

<Target Name="MarkGeneratedFiles">
  <PropertyGroup>
    <GeneratedFilePath>$(MSBuildThisFileDirectory)obj\$(Configuration)\$(TargetFramework)\$(MSBuildProjectName).Program.cs</GeneratedFilePath>
  </PropertyGroup>

  <InsertIntoFile FilePath="$(GeneratedFilePath)" LineNumber="1" Text="// &lt;auto-generated/&gt;" />
</Target>

<!-- Code taken from http://stackoverflow.com/a/21500030/4077294 -->
<UsingTask
  TaskName="InsertIntoFile"
  TaskFactory="CodeTaskFactory"
  AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
  <ParameterGroup>
    <FilePath ParameterType="System.String" Required="true" />
    <LineNumber ParameterType="System.Int32" Required="true" />
    <Text ParameterType="System.String" Required="true" />
  </ParameterGroup>
  <Task>
    <Using Namespace="System" />
    <Using Namespace="System.IO" />
    <Code Type="Fragment" Language="cs">
      <![CDATA[
        // By tradition, text file line numbering is 1-based
        var lines = File.Exists(FilePath) 
                              ? File.ReadAllLines(FilePath).ToList() 
                              : new List<String>(1);
        lines.Insert(Math.Min(LineNumber - 1, lines.Count), Text);
        File.WriteAllLines(FilePath, lines);
        return true;
      ]]>
    </Code>
  </Task>
</UsingTask>
"C:\cygwin64\home\james\Code\cs\BasicCompiler\src\BasicCompiler.Tests\BasicCompiler.Tests.csproj" (default target) (1) ->
(MarkGeneratedFiles target) ->
  C:\cygwin64\home\james\Code\cs\BasicCompiler\src\BasicCompiler.Tests\BasicCompiler.Tests.csproj(68,5): error MSB4018: The "InsertIntoFile" task failed unexpectedly.\r
C:\cygwin64\home\james\Code\cs\BasicCompiler\src\BasicCompiler.Tests\BasicCompiler.Tests.csproj(68,5): error MSB4018: System.IO.DirectoryNotFoundException: Could not find
a part of the path 'C:\cygwin64\home\james\Code\cs\BasicCompiler\src\BasicCompiler.Tests\obj\Debug\netcoreapp1.0\BasicCompiler.Tests.Program.cs'.\r