使用Microsoft.Build.Evaluation解决实际的引用路径 [英] Resolve actual Reference path using Microsoft.Build.Evaluation

查看:50
本文介绍了使用Microsoft.Build.Evaluation解决实际的引用路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用小型C#控制台应用程序中的Microsoft.Build.Evaluation工具对csproj文件进行自省和分析.我想使用与MSBuild本身相同的试探法来找到参考项目的实际位置,即

I'm doing some introspection and analysis of csproj files using the Microsoft.Build.Evaluation tools in a small C# console app. I want to locate the actual location of Reference items, using the same heuristics as MSBuild itself ie the locations described here. I'm heading towards auto conversion of build artifacts into packages, similar to what's outlined on the JetBrains blog here

我能找到的唯一示例期望HintPath是正确的,例如这个项目,我知道有些当前不正确的提示路径,我不想信任它们.这个项目非常接近我想要做的事情,但又增加了复杂性,我想使用实际的解析行为来找到依赖项.

The only examples I can find expect the HintPath to be correct, for example this project, and I know there are some HintPaths that are not currently correct, I don't want to trust them. This project very close what I'm trying to do, with the added complication that I want to use real resolution behaviour to find dependencies.

我有一个用于csproj的Microsoft.Build.Evaluation.Project对象的实例,并且看不到任何可用的方法可以为我提供解决方案.我想我想要的是用于Reference或ProjectItem的神奇Resolve()方法,有点像

I have an instance of a Microsoft.Build.Evaluation.Project object for my csproj, and I can't see any methods available on it that could exersize the resolution for me. I think what I'm hoping for is a magic Resolve() method for a Reference or a ProjectItem, a bit like this method.

通过将自己的搜索限制在此构建系统使用的一组有限的输出路径上,我可能可以找到另一种选择,但是我想尽可能地加入MSBuild.

I can probably find an alternative by constraining my own search to a set of limited output paths used by this build system, but I'd like to hook into MSBuild if I can.

推荐答案

参考分辨率是MSBuild最棘手的部分之一.程序集如何定位的逻辑是在一组标准任务内实现的: ResolveAssemblyReference

The reference resolution is one of the trickiest parts of MSBuild. The logic of how assemblies are located is implemented inside the a standard set of tasks: ResolveAssemblyReference, ResolveNativeReference, etc. The logic is how this works is very complicated, you can see that just by looking at number of possible parameters to those tasks.

但是,您无需知道查找引用文件位置的确切逻辑.有一些标准目标,称为"ResolveAssemblyReferences","ResolveProjectReferences",还有一些更专门用于本机引用(COM引用)的目标.这些目标是作为常规构建的一部分执行的.如果仅分别执行这些目标,则可以找出所需的返回值. IDE使用相同的机制来获取裁判的位置,例如智能感知,自省等.

However you don't need to know the exact logic to find the location of referenced files. There are standard targets called "ResolveAssemblyReferences", "ResolveProjectReferences" and some others more specialized for native references, COM references. Those targets are executed as part of the normal build. If you just execute those targets separately, you can find out the return values, which is exactly what you need. The same mechanism is used by IDE to get location of refereces, for Intellisense, introspection, etc.

这是您可以通过代码执行的操作:

Here is how you can do it in code:

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);
        }
    }
}

注意,将调用引擎以调用项目中的特定目标.您的项目通常不会生成,但是某些目标可能会被先决条件目标调用.

Notice, the engine is called to invoke specific targets in the project. Your project usually does not build, but some targets might be invoked by pre-requisite targets.

只需编译它,然后将打印所有依赖项的子集.如果对项目使用COM引用或本机依赖关系,则可能会有更多依赖关系.修改样本以获取样本也应该很容易.

Just compile it and will print a sub-set of all dependencies. There might be more dependencies if you use COM references or native dependencies for your project. It should be easy to modify the sample to get those as well.

这篇关于使用Microsoft.Build.Evaluation解决实际的引用路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆