1

I want to get access to an intance of this. http://msdn.microsoft.com/en-us/library/microsoft.build.buildengine.project_members(v=vs.85).aspx

From within an MSBuild task

Simon
  • 33,714
  • 21
  • 133
  • 202
  • Why? You are not supposed to access project information from within a task. MSBuild object model was explicitly designed to keep task isolated. Everything that task needs has to be passed as a parameter, so that whenever you call into the task, you know exactly what this task takes and what it produces. – seva titov Dec 24 '11 at 00:37
  • @SevaTitov i understand this. but is is a pain for user of my task to have to pass in many params every time they use my task. things like solutionpath are environmental and should be accessible from within a task. – Simon Dec 24 '11 at 00:44
  • What kind of params does your user need to pass, that you are, instead, trying to get from the Project instance? – radical Dec 24 '11 at 13:33

2 Answers2

1

you can reference macros in your build file for the project as described here: http://msdn.microsoft.com/en-us/library/c02as0cs.aspx

the project class you are referencing above is part of the api for Microsoft.Build.BuildEngine that can be programmed from a .net program

feel free to better clarify what you're trying to accomplish

Richard Logwood
  • 3,163
  • 23
  • 19
  • ok I have an instance of Microsoft.Build.BuildEngine but from that how do i get to an instance of project. – Simon Dec 24 '11 at 00:37
  • and note your first point about "reference macros in your build file" is not valid because I am talking at the Task level and dont have the ability to dictate project file changes – Simon Dec 24 '11 at 00:38
  • create an instance of the Project class and call it's Load method: http://msdn.microsoft.com/en-us/library/ms124043(v=VS.85).aspx, http://msdn.microsoft.com/en-us/library/microsoft.build.buildengine.project_members(v=VS.85).aspx, http://msdn.microsoft.com/en-us/library/microsoft.build.buildengine.project.load(v=VS.85).aspx – Richard Logwood Dec 24 '11 at 00:41
  • @ Simon: check out the example code on this thread: http://stackoverflow.com/questions/5169841/msbuild-define-subprojects-build-configuration-in-buildengine – Richard Logwood Dec 24 '11 at 00:46
0

I believe the accepted answer to this post also answers this question well.

Code copied from linked 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);

I found this technique useful when I needed to access project macro values and project settings from within an MSBuild task that validates the project settings: I preferred to query for needed info, instead of passing macro values via args.

Community
  • 1
  • 1
  • right you are. i had forgotten about this question by the time i found the other solution. I cant really mark an answer that says "go to this link" as correct. but if you re-post the code from that other answer here I will mark your answer as correct. – Simon May 07 '13 at 22:30