首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Microsoft.Build.Evaluation解析实际参考路径

使用Microsoft.Build.Evaluation解析实际参考路径
EN

Stack Overflow用户
提问于 2015-08-01 08:20:26
回答 1查看 1.5K关注 0票数 5

我正在使用Microsoft.Build.Evaluation工具在一个小型C#控制台应用程序中对csproj文件进行一些反思和分析。我希望使用与MSBuild本身相同的启发式方法(即描述这里的位置)来定位参考项的实际位置。我的目标是将构建工件自动转换为包,类似于JetBrains博客这里中概述的内容

我能找到的唯一例子是HintPath是正确的,例如这个项目,而且我知道有一些HintPaths目前是不正确的,我不想相信它们。这个项目非常接近我想要做的事情,更复杂的是,我想使用真正的解析行为来查找依赖项。

我有一个用于csproj的Microsoft.Build.Evaluation.Project对象的实例,并且我无法在它上看到任何可以为我执行分辨率的方法。我认为我希望的是一个用于引用或ProjectItem的神奇的解析()方法,有点像这种方法

通过将自己的搜索限制在这个构建系统使用的一组有限的输出路径上,我可能会找到另一种选择,但如果可以的话,我想要连接到MSBuild。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-08-01 17:34:32

参考分辨率是MSBuild中最棘手的部分之一。程序集定位的逻辑是在标准的一组任务中实现的:ResolveAssemblyReferenceResolveNativeReference等。逻辑是这样非常复杂的,您可以通过查看这些任务的可能参数来看出这一点。

然而,您不需要知道确切的逻辑来找到所引用文件的位置。有一些名为"ResolveAssemblyReferences“、"ResolveProjectReferences”的标准目标,以及其他一些对本机引用( COM引用)更为专门的目标。这些目标作为正常构建的一部分执行。如果只分别执行这些目标,就可以找到返回值,这正是您所需要的。IDE也使用同样的机制来获取引用的位置,用于智能感知、内省等等。

下面是如何在代码中这样做:

代码语言:javascript
复制
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引用或本机依赖项,则可能会有更多的依赖项。应该可以很容易地修改样本以获得这些数据。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31759821

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档