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

MSBuild not found when only Build Tools are installed #100

Closed louis-z closed 3 years ago

louis-z commented 3 years ago

MSBuildLocator.RegisterDefaults() does not use MSBuild.exe's location when only the build tools are installed, not the whole IDE.

Does it use the same logic as this vswhere command?

C:\Program Files (x86)\Microsoft Visual Studio>"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -all -prerelease -find **/MSBuild.exe
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\amd64\MSBuild.exe
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\MSBuild.exe

I believe it should instead behave as the following command:

C:\Program Files (x86)\Microsoft Visual Studio>"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -products * -find **/MSBuild.exe
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\amd64\MSBuild.exe
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\MSBuild.exe
C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\amd64\MSBuild.exe
C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\MSBuild.exe

Note that replacing MSBuildLocator.RegisterDefaults() with something like the following ends up yielding the desired behavior:

var latestInstance = MSBuildLocator.QueryVisualStudioInstances().OrderByDescending(i => i.Version).First();
MSBuildLocator.RegisterInstance(latestInstance);
Forgind commented 3 years ago

Hi @louis-z,

Can you clarify what the undesirable behavior you're seeing is? The code you pasted at the bottom is almost identical to what MSBuildLocator.RegisterDefaults() does—the only differences being that you sorted the instances it found before returning the first one, and your version filters out instances with the wrong discovery type.

louis-z commented 3 years ago

Can you clarify what the undesirable behavior you're seeing is? The code you pasted at the bottom is almost identical to what MSBuildLocator.RegisterDefaults() does—the only differences being that you sorted the instances it found before returning the first one, and your version filters out instances with the wrong discovery type.

I have this setup where

are installed. From that setup, I would expect MSBuildLocator.RegisterDefaults() to select the highest version of MSBuild available, thus the one that comes with the VS2019 build tools. Unfortunately, it seems to pick instead the highest MSBuild version from full IDE installations.

BTW I'm using Microsoft.Build.Locator version 1.2.6.

Forgind commented 3 years ago

RegisterDefaults doesn't work very hard to choose the best version, partially because what "the best" version is varies per user experience. As an example, you would like the newest version, which makes sense, but someone else could want the oldest version because it's probably the most stable, or the newest version that came with a full VS install, or...

You can see there are a lot of possible ways it could determine which is best. I'd recommend using RegisterInstance, as you suggested, since it lets you specify which you want.

louis-z commented 3 years ago

Sounds good. Closing the issue.