2012-10-24 9 views
6

コンソールアプリケーションではなく、MSBuildのタスクでのワークスペースのロードコンソールアプリケーションで同じプロジェクトを実行すると、同じコードが正常に実行されます。ロスリン:私は、このコマンドを使用して、カスタムのMSBuildタスクを持っている

アイデア?グーグルが役に立たなかった!

+0

ここで同じ問題が発生します。誰でも? – kzu

+0

@kzuは誰かが答えたように見えます。 –

答えて

-1

これはMSBuildの制限事項です。 Roslynはビルド中にMSBuildを再帰的に呼び出して、プロジェクトのプロパティ/ファイル/参照を判断することはできません。ビルド作業中にRoslyn IProjectを作成するには、代わりにLoadFromCommandLineArgs()メソッドを使用してみてください。あなたは、CscTaskがコンパイラに渡されるのと同じ引数を取るようにあなたのタスクを構築する必要があります。

希望すると便利です。

3

ここでは、RoslynのサンプルMsBuildタスクを示します。

Workspace.LoadProjectFromCommandLineArgumentsメソッドで必要なコマンドラインを再構築するには、msbuildファイルの情報をタスクに渡す必要があります。

  • 参照されるアセンブリ: @(ReferencePath)アイテムグループ。
  • コンパイルするcsファイル:@(コンパイル)アイテムグループ。
  • ベースディレクトリ:$(MSBuildProjectDirectory)ビルトインプロパティ。

これは、Roslynがソースファイルを解析するのに必要なことです。 (この記事の末尾の注釈を参照してください)

C#クラスライブラリプロジェクトを作成します。 これらはあなたが必要とするプロジェクト参照している:あなたの最後に次の行を追加し、それが実際に機能することを実証するために

using Microsoft.Build.Framework; 
using Microsoft.Build.Utilities; 
using Roslyn.Services; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace RoslynMsBuildTask 
{ 
    public class RoslynTask : Task 
    { 
     [Required] 
     public ITaskItem[] ReferencePath { get; set; } 

     [Required] 
     public ITaskItem[] Compile { get; set; } 

     [Required] 
     public ITaskItem BaseDirectory { get; set; } 

     public override bool Execute() 
     { 
      Log.LogMessage(MessageImportance.High, "RoslynTask.Execute called...\n"); 

      // Format the command line with the minimal info needed for Roslyn to create a workspace. 
      var commandLineForProject = string.Format("/reference:{0} {1}", 
       ReferencePath.Select(i => i.ItemSpec).ToSingleString(",", "\"", "\""), 
       Compile.Select(i => i.ItemSpec).ToSingleString(" ", "\"", "\"")); 

      // Create the Roslyn workspace. 
      var workspace = Workspace.LoadProjectFromCommandLineArguments("MyProject", "C#", commandLineForProject, BaseDirectory.ItemSpec); 

      // Make sure that Roslyn actually parsed the project: dump the source from a syntax tree to the build log. 
      Log.LogMessage(MessageImportance.High, workspace.CurrentSolution.Projects.First() 
       .Documents.First(i => i.FilePath.EndsWith(".cs")).GetSyntaxRoot().GetText().ToString()); 

      return true; 
     } 
    } 

    public static class IEnumerableExtension 
    { 
     public static string ToSingleString<T>(this IEnumerable<T> collection, string separator, string leftWrapper, string rightWrapper) 
     { 
      var stringBuilder = new StringBuilder(); 

      foreach (var item in collection) 
      { 
       if (stringBuilder.Length > 0) 
       { 
        if (!string.IsNullOrEmpty(separator)) 
         stringBuilder.Append(separator); 
       } 

       if (!string.IsNullOrEmpty(leftWrapper)) 
        stringBuilder.Append(leftWrapper); 

       stringBuilder.Append(item.ToString()); 

       if (!string.IsNullOrEmpty(rightWrapper)) 
        stringBuilder.Append(rightWrapper); 
      } 

      return stringBuilder.ToString(); 
     } 
    } 
} 

Microsoft.Build.Framework 
Microsoft.Build.Utilities.v4.0 
Roslyn.Compilers 
Roslyn.Services 

カスタムのMSBuildタスクのためのコードcsprojファイル(プロジェクトの終了タグの直前)。しかし、プロジェクトが既に正常に構築されていて、出力フォルダにタスクdllが見つかる場合に限ります。

<Target Name="AfterBuild" DependsOnTargets="RoslynTask"/> 
    <UsingTask AssemblyFile="$(OutputPath)\RoslynMsBuildTask.dll" TaskName="RoslynMsBuildTask.RoslynTask" /> 
    <Target Name="RoslynTask"> 
    <RoslynTask ReferencePath="@(ReferencePath)" Compile="@(Compile)" BaseDirectory="$(MSBuildProjectDirectory)" /> 
    </Target> 

これは、最初のcsファイルのソースをビルド出力にダンプします。


(などConditionalDirectives、出力タイプ、など)他のcsc.exeスイッチもかかわらあなたがやろうとしている分析の種類に応じてことがあります。このパターンを使用してタスクに渡すこともできます。 MsBuildがcsc.exeに渡すプロパティの完全なリストについては、$(MSBuildToolsPath)\ Microsoft.CSharp.targetsファイル、CoreCompileターゲット、Cscタスクを参照してください。

+0

ConditionalDirectives、出力タイプなどの他のスイッチは、実行しようとしている分析のタイプに応じて異なるかもしれませんが、これは素晴らしい出発点です! –

+0

@ケビン:情報ありがとう、私は私の答えに追加しました。 – Vizu

+0

私にとっては、これと同じ例外があります。 ( 'Roslyn.Utilities.SerializableDataStorage'と入力して透過プロキシをキャストすることはできません) – Imi

関連する問題