参考解析是 MSBuild 中最棘手的部分之一。如何定位程序集的逻辑在一组标准任务中实现:
ResolveAssemblyReference、ResolveNativeReference 等。其工作原理的逻辑非常复杂,您只需查看这些任务的可能参数数量即可看出这一点。
但是,您无需知道查找引用文件位置的确切逻辑。有称为“ResolveAssemblyReferences”、“ResolveProjectReferences”的标准目标和一些更专门用于本机引用、COM 引用的其他目标。这些目标作为正常构建的一部分执行。如果你只是单独执行这些目标,你可以找出返回值,这正是你所需要的。 IDE 使用相同的机制来获取引用的位置,用于 Intellisense、内省等。
以下是您可以在代码中执行此操作的方法:
using Microsoft.Build.BuildEngine;
using Microsoft.Build.Execution;
using Microsoft.Build.Framework;
using System;
using System.Collections.Generic;
class Program
{
static int Main(string[] args)
{
if (args.Length < 1)
{
Console.WriteLine("Usage: GetReferences.exe <projectFileName>");
return -1;
}
string projectFileName = args[0];
ConsoleLogger logger = new ConsoleLogger(LoggerVerbosity.Normal);
BuildManager manager = BuildManager.DefaultBuildManager;
ProjectInstance projectInstance = new ProjectInstance(projectFileName);
var result = manager.Build(
new BuildParameters()
{
DetailedSummary = true,
Loggers = new List<ILogger>() { logger }
},
new BuildRequestData(projectInstance, new string[]
{
"ResolveProjectReferences",
"ResolveAssemblyReferences"
}));
PrintResultItems(result, "ResolveProjectReferences");
PrintResultItems(result, "ResolveAssemblyReferences");
return 0;
}
private static void PrintResultItems(BuildResult result, string targetName)
{
var buildResult = result.ResultsByTarget[targetName];
var buildResultItems = buildResult.Items;
if (buildResultItems.Length == 0)
{
Console.WriteLine("No refereces detected in target {0}.", targetName);
return;
}
foreach (var item in buildResultItems)
{
Console.WriteLine("{0} reference: {1}", targetName, item.ItemSpec);
}
}
}
注意,调用引擎是为了调用项目中的特定目标。您的项目通常不会构建,但某些目标可能会被先决条件目标调用。
只需编译它并打印所有依赖项的子集。如果您对项目使用 COM 引用或本机依赖项,则可能会有更多依赖项。应该很容易修改示例以获取这些示例。