2016-12-25 55 views
2

背景: StyleCop抱怨自動生成的文件格式不良,導致在嘗試構建項目時出現很多警告。自動生成的文件位於我項目的obj/目錄中,並且我想創建一個MSBuild任務,在編譯之前(但在生成它之後)將此文件預加// <auto-generated/>,以便StyleCop不會發生抱怨。如何在編譯開始之前運行MSBuild任務,但在生成中間文件之後?

問題:我有以下的MSBuild代碼

<!-- 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> 

,我要修改的文件名爲obj/Debug/netcoreapp1.0/BasicCompiler.Tests.Program.cs文件。在上面的代碼片段中,我有一個BeforeCompile目標取決於MarkGeneratedFiles,它繼續並嘗試在該文件的第一行之前插入// <auto-generated/>

我測試過了,如果生成的文件已經存在,這似乎工作正常。但是,如果我刪除obj/目錄或者我從另一臺機器建立,我得到這個錯誤:

"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 

基本上好像目標文件之前得到運行是如何產生,所以沒有什麼預先設置文本至。有沒有辦法運行它之後這個文件得到了生成,但之前編譯?

其他注意事項:到目前爲止,我已經完成了所有特殊的目標名稱here的看了看,同時使用BeforeBuildBeforeCompile嘗試。

此外,由於我使用「新」StyleCop,我不能把<ExcludeFromStyleCop>放在我的項目文件中。見https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/1145

+2

除非sombody知道所有建立由心臟步驟的解決方案是運行與診斷手搖對詳細的版本(可在VS中設置某個地方,或通過/ V:d的命令行),然後再通過輸出 - 將列出所有目標 - 並找出哪個是生成文件的。然後將'AfterTargets =「」'添加到您的MarkGeneratedFiles目標中(不需要BeforeCompile等)0 – stijn

+0

@stijn非常感謝您!我能夠追蹤正在生成的目標(它被稱爲'GenerateProgramFile')並將'AfterTargets ='GenerateProgramFile''放入我的目標中,一切正常,現在可以正常工作。 –

+0

@ ColeWu-MSFT當然。我已經發布了我的問題的答案,但是我不能接受我自己的答案6個小時以上。 –

回答

1

我設法解決這個問題;請參閱@ stijn的超有用評論here

  • 首先,我從命令行運行msbuild /v:detailed。這增加了MSBuild的詳細程度,以便更詳細地瞭解正在發生的事情,例如,您可以看到正在運行的每個目標的名稱。

  • 我在日誌中搜索了生成文件的目標名稱。就我而言,原來是GenerateProgramFiles

  • 我用AfterTargets="GenerateProgramFiles"標記了我的自定義目標,因此它在生成文件後運行。

相關問題