4

I'm attempting to programmatically build a project which uses C#7, and therefore MSBuild 15, but this task is failing seemingly because of mismatched assembly references.

Here is my code:

        string projectFilePath = Path.Combine(args.Any() ? args.First() :@"C:\Users\newsoni\Documents\Visual Studio 2017\Projects\ConsoleApp2\ConsoleApp2.sln");

        ProjectCollection pc = new ProjectCollection();
        Dictionary<string, string> globalProperty = new Dictionary<string, string>();
        globalProperty.Add("Configuration", "Debug");
        globalProperty.Add("Platform", "x86");

        BuildParameters bp = new BuildParameters(pc);
        bp.Loggers = new ILogger[] { new Logger(), new ConsoleLogger(),  };
        BuildRequestData BuidlRequest = new BuildRequestData(projectFilePath, globalProperty, "4.0", new string[] { "Build" }, null);
        BuildResult buildResult = BuildManager.DefaultBuildManager.Build(bp, BuidlRequest);

Here is the error message:

C:\Users\newsoni\Documents\Visual Studio 2017\Projects\ConsoleApp2\ConsoleApp2.sln.metaproj : error MSB4127: The "Error" task could not be instantiated from the assembly "Microsoft.Build.Tasks.v4.0, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a". Please verify the task assembly has been built using the same version of the Microsoft.Build.Framework assembly as the one installed on your computer and that your host application is not missing a binding redirect for Microsoft.Build.Framework. Unable to cast object of type 'Microsoft.Build.Tasks.Error' to type 'Microsoft.Build.Framework.ITask'.
C:\Users\newsoni\Documents\Visual Studio 2017\Projects\ConsoleApp2\ConsoleApp2.sln.metaproj : error MSB4060: The "Error" task has been declared or used incorrectly, or failed during construction. Check the spelling of the task name and the assembly name.

Here is a link to a project you can use to recreate the issue:

https://drive.google.com/a/xibis.com/file/d/0B-mqMIMqm_XHcVRJQmtxQkd1b3c/view?usp=sharing

You will have to change the path in the code to a project on your own machine, but it doesn't seem to matter if this is a VS 2017 project or earlier.

One other thing that may or may not be relevant, I noticed that the Microsoft.WebApplication.Build.Tasks.Dll in this folder:

C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v15.0\WebApplications

Still seems to be referencing Microsoft.Build.Framework.dll version 14, not 15 as I would have expected.

Ian Newson
  • 7,679
  • 2
  • 47
  • 80
  • 1
    The drastically reorganized VS install procedure is causing a lot of havoc. The MSBuild version you want is stored in C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin on my machine. Probably not yours, but in the neighborhood. How anybody is supposed to find it there, and do so consistently from one machine to another, is a big mystery to me. No docs, no blogs, no answers here. – Hans Passant Apr 27 '17 at 17:06
  • @HansPassant thanks Hans. Yes you're correct. I've found the DLLs you mentioned, but then went the nuget route due to other issues. I suspect this issue has been complicated by well intentioned but ultimately harmful dynamic plugin loading code. – Ian Newson Apr 27 '17 at 19:09
  • You got a point, that is probably the correct approach. I suspect it has more to do with shipping untested code and being able to quickly bugfix it when somebody yells loud enough. Consider posting a link to the Nuget package for future victims. – Hans Passant Apr 27 '17 at 19:23
  • @HansPassant Hi Hans. Sorry I think you misunderstand. I've had several issues with referencing the correct MSBuild versions and only after I went the nuget route did I give up and post this question. I still have no solution. – Ian Newson May 08 '17 at 15:15

3 Answers3

7

It turns out there are two issues in my test project. The first is due to the naming of the project.

However there is a second issue which is due to the references not being correct. To use MSBuild 15 programmtically you must install the following packages:

Install-Package Microsoft.Build -Version 15.1.1012
Install-Package Microsoft.Build.Framework -Version 15.1.1012
Install-Package Microsoft.Build.Tasks.Core -Version 15.1.1012
Install-Package Microsoft.Build.Utilities.Core -Version 15.1.1012
Install-Package Microsoft.Net.Compilers -Version 2.2.0

There is one more step which is nuts and completely undiscoverable. You must now add a reference to this DLL which should be relative to your solution folder:

packages\Microsoft.Net.Compilers.2.2.0\tools\Microsoft.Build.Tasks.CodeAnalysis.dll

Ian Newson
  • 7,679
  • 2
  • 47
  • 80
0

I opened a support ticket with Microsoft and they have confirmed that this is a bug in Visual Studio 2017.

They are aiming to get a fix for this into update 3 for Visual Studio, but this may slip.

This issue tracks the bug:

https://github.com/Microsoft/msbuild/issues/2194

There is no workaround at present for this API, but you can invoke the MSBuild exe using Process as an alternative.

Ian Newson
  • 7,679
  • 2
  • 47
  • 80
0

If you have MSBuild installed on your PC, either directly or through Visual Studio, the proper fix is to use the package Microsoft.Build.Locator which will find that installed version and execute the build using it.

Install these packages

Microsoft.Build
Microsoft.Build.Framework
Microsoft.Build.Locator

The first 2 are needed so that the code can compile but should be excluded from the project output.

In your application startup add the following line of code, this only has to run once.

Microsoft.Build.Locator.MSBuildLocator.RegisterDefaults();

Remove any additional binding redirects in your app.config that are specific to Microsoft.Build or other build libraries. The call to the Microsoft.Build.Locator assembly will ensure that these redirects take place automatically.

References

Igor
  • 60,821
  • 10
  • 100
  • 175