microsoft / MSBuildLocator

An API to locate MSBuild assemblies from an installed Visual Studio location. Use this to ensure that calling the MSBuild API will use the same toolset that a build from Visual Studio or msbuild.exe would.
Other
218 stars 83 forks source link

Could not load file or assembly Microsoft.Build, Version=15.1.0.0 #64

Closed jliglesias66 closed 5 years ago

jliglesias66 commented 5 years ago

Steps to reproduce

Following the steps in this article https://docs.microsoft.com/en-us/visualstudio/msbuild/updating-an-existing-application?view=vs-2019

  1. Create C# project console in VS2017 with Framework 4.7.2 (I also have the VS2019 installed)
  2. Add PackageReferences (see down) in .csproj file
  3. Add next code

        static void Main(string[] args)
        {
            MSBuildLocator.RegisterDefaults();
            string projectPath = @"C:\Projects\TestProject.vbproj";
            var project = new Microsoft.Build.Evaluation.Project(projectPath);
        }

    .csproj file

    <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
    <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
    </PropertyGroup>
    
    <ItemGroup>
    <PackageReference Include="Microsoft.Build" Version="16.0.461" ExcludeAssets="runtime"/>
    <PackageReference Include="Microsoft.Build.Utilities.Core" Version="16.0.461" ExcludeAssets="runtime"/>
    <PackageReference Include="Microsoft.Build.Locator" Version="1.2.2" />
    <PackageReference Include="Microsoft.CodeAnalysis.VisualBasic.Workspaces" Version="3.0.0" />
    <PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="3.0.0" />
    </ItemGroup>
    </Project>

The project compiles fine but in runtime it shows the following message: "The application is in break mode" exception "Could not load file or assembly Microsoft.Build, Version=15.1.0.0"... What am I doing wrong?

rainersigwald commented 5 years ago

The .NET assembly loader tries to load all types referenced within a method before loading the method, so before it starts running your Main method, it tries to locate MSBuild assemblies. Since the Locator isn't set up until the first line inside the method, that fails.

This is mentioned in the doc page you linked,

Add a call to the Locator API before calling any method that uses MSBuild.

but it's a pretty subtle behavior. If you have any ideas about how to call it out more clearly in the documentation, we'd love to hear them.

rainersigwald commented 5 years ago

Closing, in the hopes that helped.

cyungmann commented 5 years ago

@rainersigwald wow, that is some devilishly tricky behavior. I spent quite a while trying to figure out why my code wasn't working. I like your idea of an analyzer, but in the meantime would it make sense for a correct vs. incorrect code example to appear on the referenced documentation page?