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

Differences in QueryVisualStudioInstances results for VS Code and Visual Studio #98

Closed fjoppe closed 3 years ago

fjoppe commented 3 years ago

Hi,

I'm trying to analyze C# code with Roslyn. This fails because MSBuildLocator.QueryVisualStudioInstances() returns incorrect values - for what I need.

I am using F# in VS Code, with .net5-preview options, because these preview options have bad performance in Visual Studio Community 2019.

This is #fsharp script (with preview options):

#r "mscorlib.dll"
#r "System.Collections.dll"
#r "System.Collections.Immutable.dll"
#r "nuget:System.Configuration.ConfigurationManager,version=4.7.0"
#r "nuget:System.Runtime, version=4.3.1"
#r "nuget:Microsoft.Build.Locator,version=1.2.6"
#r "nuget:Microsoft.Build, version=15.1.0"
#r "nuget:Microsoft.Build.Framework, version=15.1.0"
#r "nuget:Microsoft.CodeAnalysis.Workspaces.MSBuild, version=3.7.0"
#r "nuget:Microsoft.CodeAnalysis.CSharp.Workspaces, version=3.7.0"
#r "nuget:Microsoft.CodeAnalysis.Common, version=3.7.0"

open Microsoft.Build.Locator
open Microsoft.CodeAnalysis.MSBuild
open Microsoft.CodeAnalysis.Diagnostics
open Microsoft
open Microsoft.CodeAnalysis
open System.Collections.Immutable
open System.Configuration
open System.Collections.Generic
open System.Collections.Immutable

let vsVersions = MSBuildLocator.QueryVisualStudioInstances()

vsVersions 

The last line produces this result in VS Code (with plugin "Ionide"):

val it : IEnumerable = seq [Microsoft.Build.Locator.VisualStudioInstance {DiscoveryType = DotNetSdk; MSBuildPath = "C:\Program Files\dotnet\sdk\5.0.100-rc.1.20452.10\"; Name = ".NET Core SDK"; Version = 5.0.100; VisualStudioRootPath = "C:\Program Files\dotnet\sdk\5.0.100-rc.1.20452.10\";}]

While the same script in Visual Studio Community 2019, the last line produces:

val it : IEnumerable = seq [Microsoft.Build.Locator.VisualStudioInstance {DiscoveryType = VisualStudioSetup; MSBuildPath = "C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\MSBuild\Current\Bin"; Name = "Visual Studio Community 2019"; Version = 16.8.30524.135; VisualStudioRootPath = "C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview";}; Microsoft.Build.Locator.VisualStudioInstance {DiscoveryType = VisualStudioSetup; MSBuildPath = "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin"; Name = "Visual Studio Community 2019"; Version = 16.7.30523.141; VisualStudioRootPath = "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community";}]

I would like the same results in both environments, or at least the Visual Studio Community 2019 results in VS Code. It's the Visual Studio results which enable me to work with the Roslyn library. Because the object of analysis is still on one of the old .Net frameworks, while my analyzer works in .net5.

I also tried with QueryOptions, but this has no results. I understand from the source code, somewhere a call is made to an external imported dll. But I don't know how to manipulate this.

rainersigwald commented 3 years ago

It's not possible to load the Visual Studio copy of MSBuild (which runs on .NET Framework) from a client application that runs on .NET 5 or .NET Core.

You have two options:

  1. Target .NET Framework for your analysis application and use the Visual Studio copies of everything (this is closest to the Visual Studio/msbuild.exe experience).
  2. Target .NET 5 for your application and use the .NET 5.0 SDK copies of everything (this is closest to the dotnet build experience).

If the object of analysis is not using the .NET (Core) SDK, only option 1 will work for you. MSBuild (as part of the .NET Core SDK) can't load older projects.

fjoppe commented 3 years ago

Thanks for responding. I can confirm what you are saying. As I'm trying to create an analyzer which plows through the full code-base of an organization, changing the target framework from the analyzed-project is not an option. I'll stick with option 1.