Answered Problem with using Roslyn in a MS Build Task

  • Friday, October 28, 2011 12:24 PM
     
      Has Code

    I am experimenting with using Roslyn in an MS Build task (BeforeBuild Target) but have run into the following problem. When executing the attached code, the last line (accessing the references) throws an Exception: "Internal MSBuild Error: Cannot create in-proc node because operating environment is already owned by another." originating from here: "Microsoft.Build.dll!Microsoft.Build.Execution.BuildManager.ExecuteSubmission.AnonymousMethod__9(object context) + 0x46 bytes"

    My setup is a test project which imports my custom task. For executing and debugging I just call MS Build through modified debug settings of my dev project with the appropriate file path to my test project.

     

     public class MyTask : Task
     {
            public override bool Execute()
            {
                string projectFileName = this.BuildEngine.ProjectFileOfTaskNode;
                var workspace = Workspace.LoadStandAloneProject(projectFileName);
                var solution = workspace.CurrentSolution;
                var project = solution.Projects.First();
                var references = project.MetadataReferences;

    ... 

     


All Replies

  • Friday, October 28, 2011 2:32 PM
    Owner
     
     

    Hi,

    Unfortunately, this isn't a scenario that we have tested much, so I don't have a simple workaround for you at the moment. The issue here is the the workspace you created will use msbuild to lazily evaluate properties such as MetadataReferences.  However, msbuild is already in the middle of a build, and isn't happy with this re-entrancy.  All I can think to of would be for you to move this logic into a separate AppDomain or process, so that you don't interfere with the state of the "outer" build.

    Thanks for letting us know about this issue - can you file a bug on connect so that we can look into making this scenario easier?

    Also - if you don't plan to ever modify the solution, you don't need to use the Workspace at all, you can just use Solution.LoadStandaloneProject too.

    -- Kevin

  • Friday, October 28, 2011 6:07 PM
     
      Has Code

    Thanks. I filed a bug on Connect here: https://connect.microsoft.com/VisualStudio/feedback/details/697724/problem-with-using-roslyn-in-a-ms-build-task#details

    I've never worked with creating additional AppDomains before and I am running into a bit of trouble. I moved the code to a new project (so I get a separate assembly that I can load into AppDomain). When trying to load the Assembly in my code I get a FileNotFoundException. Looking into the Binding Logs didn't really get me any further. I also tried setting up the Bin-Path on the AppDomainSetup but it still didn't work. I can't even seem to load the origonal Assembly into a new AppDomain.

     

    var appDomainSetup = new AppDomainSetup();
    var appDomain = AppDomain.CreateDomain("Hallo"nullappDomainSetup);
    var assembly = appDomain.Load(AssemblyName.GetAssemblyName(@"C:\..."));

     

  • Friday, October 28, 2011 7:39 PM
    Owner
     
     Answered Has Code

    A  simpler work-around for the time being may be to just avoid the Workspace API for this scenario.  Since you already have access to MSBuild, you can create a Compilation object yourself (with a little effort):

    public class MyTask : Task
    {
        public override bool Execute()
        {
            var projectFileName = this.BuildEngine.ProjectFileOfTaskNode;
            var project = ProjectCollection.GlobalProjectCollection.GetLoadedProjects(this.BuildEngine.ProjectFileOfTaskNode).Single();
     
            var compilation = Compilation.Create(project.GetPropertyValue("AssemblyName"),
                syntaxTrees: project.GetItems("Compile").Select(c => SyntaxTree.ParseCompilationUnit(c.EvaluatedInclude)),
                references: project.GetItems("Reference").Select(r => MetadataReference.Create(r.EvaluatedInclude)));
            
            // Now work with compilation ...
        }
    }

    This is basically what the Workspace is doing 'under the covers.'

    Hope that helps

  • Saturday, October 29, 2011 9:20 AM
     
     
    That seems to work, thanks.