【问题标题】:From within an MSBuild task how do I get access to the "Project" instance?如何从 MSBuild 任务中访问“项目”实例?
【发布时间】:2024-01-11 23:02:01
【问题描述】:

【问题讨论】:

  • 为什么?您不应该从任务中访问项目信息。 MSBuild 对象模型被明确设计为保持任务隔离。任务所需的所有内容都必须作为参数传递,这样无论何时调用该任务,您都可以准确地知道该任务需要什么以及产生什么。
  • @SevaTitov 我明白这一点。但是对于我的任务的用户来说,每次使用我的任务时都必须传递许多参数是一种痛苦。像解决方案路径这样的东西是环境的,应该可以从任务中访问。
  • 您的用户需要传递什么样的参数,而您却试图从项目实例中获取?

标签: .net visual-studio msbuild


【解决方案1】:

您可以在项目的构建文件中引用宏,如下所述:http://msdn.microsoft.com/en-us/library/c02as0cs.aspx

您在上面引用的项目类是 Microsoft.Build.BuildEngine api 的一部分,可以从 .net 程序进行编程

请随时更好地阐明您要完成的工作

【讨论】:

【解决方案2】:

我相信the accepted answer to this post 也很好地回答了这个问题。

从链接帖子复制的代码:

public static class BuildEngineExtensions
{
    const BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Public;

    public static IEnumerable GetEnvironmentVariable(this IBuildEngine buildEngine, string key,bool throwIfNotFound)
    {
        var projectInstance = GetProjectInstance(buildEngine);

        var items = projectInstance.Items
            .Where(x => string.Equals(x.ItemType, key, StringComparison.InvariantCultureIgnoreCase)).ToList();
        if (items.Count > 0)
        {
            return items.Select(x => x.EvaluatedInclude);
        }


        var properties = projectInstance.Properties
            .Where(x => string.Equals(x.Name, key, StringComparison.InvariantCultureIgnoreCase)).ToList();
        if (properties.Count > 0)
        {
            return properties.Select(x => x.EvaluatedValue);
        }

        if (throwIfNotFound)
        {
            throw new Exception(string.Format("Could not extract from '{0}' environmental variables.", key));
        }

        return Enumerable.Empty();
    }

    static ProjectInstance GetProjectInstance(IBuildEngine buildEngine)
    {
        var buildEngineType = buildEngine.GetType();
        var targetBuilderCallbackField = buildEngineType.GetField("targetBuilderCallback", bindingFlags);
        if (targetBuilderCallbackField == null)
        {
            throw new Exception("Could not extract targetBuilderCallback from " + buildEngineType.FullName);
        }
        var targetBuilderCallback = targetBuilderCallbackField.GetValue(buildEngine);
        var targetCallbackType = targetBuilderCallback.GetType();
        var projectInstanceField = targetCallbackType.GetField("projectInstance", bindingFlags);
        if (projectInstanceField == null)
        {
            throw new Exception("Could not extract projectInstance from " + targetCallbackType.FullName);
        }
        return (ProjectInstance)projectInstanceField.GetValue(targetBuilderCallback);
    }
}


// Sample useage:
string targetPath = buildEngine.GetEnvironmentVariable("TargetPath", true).First();
string intermediateAssembly = buildEngine.GetEnvironmentVariable("IntermediateAssembly", true).First();
IEnumerable<string> referencePaths = buildEngine.GetEnvironmentVariable("ReferencePath", true);

当我需要从验证项目设置的 MSBuild 任务中访问项目宏值和项目设置时,我发现这种技术很有用:我更喜欢查询所需的信息,而不是通过 args 传递宏值。

【讨论】:

  • 没错。当我找到其他解决方案时,我已经忘记了这个问题。我不能真正将“转到此链接”的答案标记为正确。但如果您在这里重新发布其他答案的代码,我会将您的答案标记为正确。
最近更新 更多