通过C#评估msbuild任务中定义的项目

我正在尝试生成目标的有向图(点格式),这些目标将以MSBuild项目文件路径作为输入进行调用。 这与ggtools.net中的grand-ui相同 (除了我正在尝试以只读图像开头)。

我希望处理3个案例:

1)目标具有DependsOnTargets属性

2)目标使用Exec任务调用MSBuild

3)目标调用MSBuild任务并传递ItemGroup

我相信我在下面的代码中主要处理#1和#2。 但是,我无法弄清楚如何获取对ItemGroup的引用。

示例MSBuild项目:

     TargetToInvoke=ParallelTarget1   TargetToInvoke=ParallelTarget2                        

但是,目标可能跨越多个项目文件。

到目前为止我管理的内容(VS2010 + .NET 4):

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using Microsoft.Build.Evaluation; using Microsoft.Build.Execution; using Microsoft.Build.Framework; namespace ConsoleApplication18 { class Program { static String ProcessMSBuildFile(System.IO.FileInfo file, ProjectTaskInstance referringTask = null) { StringBuilder sb = new StringBuilder(); sb.AppendLine("subgraph cluster_" + file.FullName.Replace(".", "_").Replace(@"\", "_").Replace(":", "_") + " {"); ProjectInstance currentProj = new ProjectInstance(file.FullName); foreach (ProjectTargetInstance target in currentProj.Targets.Values) { if (String.IsNullOrWhiteSpace(target.DependsOnTargets)) { sb.AppendLine(target.Name + ";"); } else { for (int i = 0; i " + currentProj.ExpandString(target.DependsOnTargets.Split(';')[i]) + ";"); } } foreach (ProjectTaskInstance task in target.Tasks) { if (task.Name == "MSBuild") { foreach (String projectPath in task.Parameters["Projects"].Split(';').AsEnumerable()) { if (projectPath.StartsWith("$")) { if (currentProj.ExpandString(projectPath) != currentProj.FullPath) { sb.Append(ProcessMSBuildFile(new System.IO.FileInfo(currentProj.ExpandString(projectPath)))); } } else if (projectPath.StartsWith("@")) { sb.AppendLine("Could not handle : " + projectPath); } } foreach (String msbuildTaskTarget in task.Parameters["Targets"].Split(';')) { if (referringTask != null) { sb.AppendLine(referringTask.Name + "->" + task.Name + ";"); } else { sb.AppendLine(task.Name + ";"); } } } else if (task.Name == "Exec") { // Get the Command. If it is MSBuild, we should process it further. if (task.Parameters.ContainsKey("Command")) { String taskCommand = currentProj.ExpandString(task.Parameters["Command"]); String executablePath = taskCommand.Substring(0, taskCommand.IndexOf(" ")); if (new System.IO.FileInfo(executablePath).Name.ToLower() == "msbuild") { String[] separator = { " " }; String projectPath = taskCommand.Split(separator, StringSplitOptions.RemoveEmptyEntries).Where(arg => !arg.StartsWith("/")).ElementAt(1); if (projectPath != currentProj.FullPath) { ProcessMSBuildFile(new System.IO.FileInfo(projectPath)); } else { foreach (String targetToBeCalled in taskCommand.Split(separator, StringSplitOptions.RemoveEmptyEntries).Where(arg => (arg.ToLower().StartsWith("/t") || arg.ToLower().StartsWith("/target")))) { sb.Append(target.Name + "->" + targetToBeCalled.Replace("/target:", "").Replace("/t:", "")); } } } } } } } sb.AppendLine("}"); return sb.ToString(); } static void Main(string[] args) { if (args.Length != 1) { System.Console.WriteLine("Please pass the path to an MSBuild project as argument.\nPress any key to quit."); System.Console.Read(); return; } if (!System.IO.File.Exists(args[0])) { System.Console.WriteLine("Input MSBuild project file does not exist.\nPress any key to quit."); System.Console.Read(); return; } StringBuilder sb = new StringBuilder(); sb.AppendLine("digraph Build {"); sb.Append(ProcessMSBuildFile(new System.IO.FileInfo(args[0]))); sb.AppendLine("}"); System.Console.WriteLine(sb); } } } 

问题在于“无法处理”部分。

我正在尝试生成的内容:

 digraph Build { subgraph cluster_C__temp_proj { Build->PrepareEnvironmentForBuild; Build->MapDrives; Build->TargetWithConfidentialSteps; Build->InvokeInParallelWithinThisProject; InvokeInParallelWithinThisProject->ParallelTarget1; InvokeInParallelWithinThisProject->ParallelTarget2; InvokeInParallelWithinThisProject; ParallelTarget1; ParallelTarget2; PrepareEnvironmentForBuild; MapDrives; TargetWithConfidentialSteps; } } 

有人可以帮助我从上面的例子中获得对ItemGroup“StepsToRunInParallel”的引用吗?

我还想过注册一个只记录的记录器:

1)项目文件名,用于生成集群/子图

2)目标名称

然后消耗该事件而不执行任何操作。 这方面的任何想法都是受欢迎的。