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
212 stars 83 forks source link

Run MSBuildLocator.RegisterInstance throw exception #287

Closed animalisme closed 2 months ago

animalisme commented 3 months ago

I want to use MSBuildWorkspace to load the solution structure automatically, so i use the MSBuildLocator to init first, but now it throw exception when run into MSBuildLocator.RegisterInstance(instance);. My visual IDE is vs2022 community, project framework is .net8.0. My code is as var instance = MSBuildLocator.QueryVisualStudioInstances().First(x=>x.Version.Major == 8); MSBuildLocator.RegisterInstance(instance); MSBuildLocator.RegisterDefaults(); MSBuildWorkspace workspace = MSBuildWorkspace.Create();

The exception message as follow:

Microsoft.Build.Locator.MSBuildLocator.RegisterInstance was called, but MSBuild assemblies were already loaded. Ensure that RegisterInstance is called before any method that directly references types in the Microsoft.Build namespace has been called. This dependency arises from when a method is just-in-time compiled, so it breaks even if the reference to a Microsoft.Build type has not been executed. For more details, see aka.ms/RegisterMSBuildLocator Loaded MSBuild assemblies: Microsoft.Build, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a Microsoft.Build.Framework, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a

Anyone can help me?

YuliiaKovalova commented 3 months ago

Hi @animalisme,

It looks like you slightly misuse: MSBuildLocator.RegisterInstance(instance); and MSBuildLocator.RegisterDefaults();

Either first of the second invocation can be used per the same VisualStudiInstance, because under the hood MSBuildLocator.RegisterDefaults(); invokes RegisterInstance: https://github.com/microsoft/MSBuildLocator/blob/198e001f14230163ea5d992fdc1dbaf256139dbc/src/MSBuildLocator/MSBuildLocator.cs#L114C13-L114C29.

So, to make your snapshot work please try the next code:

using Microsoft.Build.Locator;
using Microsoft.CodeAnalysis.MSBuild;

var instance = MSBuildLocator.QueryVisualStudioInstances().First(x => x.Version.Major == 8); 
MSBuildLocator.RegisterInstance(instance);

// This is an extra call that causes the error.
// MSBuildLocator.RegisterDefaults(); 

// It's a disposable object, so we should use it in a using block.
using (MSBuildWorkspace workspace = MSBuildWorkspace.Create())
{
    var project = await workspace.OpenSolutionAsync(@"C:\Users\ykovalova\source\repos\CPS1\CPS1.sln");
    Console.WriteLine(project.Version);
}

Please let me know if it works for you.

animalisme commented 3 months ago

@YuliiaKovalova ,thank you for your reply.But it doesn't work, in fact, it throw exception when it run to MSBuildLocator.RegisterInstance(instance); I use MSBuildLocator.QueryVisualStudioInstances() to get VisualStudio Instances ,there is only one instance i got, i am not sure whether it is a correct msbuild instance.

animalisme commented 3 months ago

The instance.MSBuildPath is : "C:\Program Files\dotnet\sdk\8.0.202", and the instance DiscoveryType = DotNetSdk, and VisualStudioRootPath = "C:\Program Files\dotnet\sdk\8.0.202"。

YuliiaKovalova commented 3 months ago

@rainersigwald, do you have any ideas what can be wrong here?

rainersigwald commented 3 months ago

@animalisme Can you share the whole function that calls MSBuildLocator? And your project file?

YuliiaKovalova commented 2 months ago

Close issue due to lack of information. Feel free to reopen if it is still relevant to you.