So the original question What's the correct usage of Microsoft.Build.Evaluation? has the following accepted answer:
project = new Project(projectPath, new Dictionary<string, string>(), "12.0", new ProjectCollection());
This does not work in 2021 with NuGet package Microsoft.Build 16.8.0.
I would like to evaluate a non SDK style project like this:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" />
...
<Import Project="..\..\..\Tools\MSBuild\Dayforce.targets" />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>
Please, observe:
Attempt 1
new Project(projectPath, new Dictionary<string, string>(), "16.0", new ProjectCollection());
Results in:
Microsoft.Build.Exceptions.InvalidProjectFileException: The tools version "16.0" is unrecognized. Available tools versions are "Current".
Attempt 2
new Project(projectPath, new Dictionary<string, string>(), "Current", new ProjectCollection());
Results in:
Microsoft.Build.Exceptions.InvalidProjectFileException: The imported project "C:\work\CSTool\CSTool\bin\Debug\netcoreapp3.1\Current\Microsoft.Common.props" was not found. Confirm that the expression in the Import declaration "C:\work\CSTool\CSTool\bin\Debug\netcoreapp3.1\Current\Microsoft.Common.props" is correct, and that the file exists on disk.
Attempt 3
new Project(projFilePath, new Dictionary<string, string>
{
["MSBuildExtensionsPath"] = @"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild",
}, "Current", new ProjectCollection());
Results in:
Microsoft.Build.Exceptions.InvalidProjectFileException: The imported project "C:\work\CSTool\CSTool\bin\Debug\netcoreapp3.1\Microsoft.CSharp.targets" was not found. Confirm that the expression in the Import declaration "C:\work\CSTool\CSTool\bin\Debug\netcoreapp3.1\Microsoft.CSharp.targets" is correct, and that the file exists on disk.
We are making progress, Microsoft.Common.props seems to have been imported and now we fail on the last import - Microsoft.CSharp.targets
Attempt 4
new Project(projFilePath, new Dictionary<string, string>
{
["MSBuildExtensionsPath"] = @"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild",
["MSBuildBinPath"] = @"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin",
}, "Current", new ProjectCollection());
But the result is:
System.ArgumentException: The "MSBuildBinPath" property name is reserved.
So, what am I missing?
I managed to do what I wanted. However, none of the Microsoft.Build NuGet packages worked as expected by me. I checked all the published versions.
What worked for me is reference the Microsoft.Build Dlls found inside the VS 2019 installation directory. Here is my project file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
...
<ItemGroup>
<Reference Include="Microsoft.Build">
<HintPath>..\..\..\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\Microsoft.Build.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Build.Framework">
<HintPath>..\..\..\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\Microsoft.Build.Framework.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Build.Utilities.Core">
<HintPath>..\..\..\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\Microsoft.Build.Utilities.Core.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
And here is the code that works:
var project = new Project(projFilePath);
foreach (var compileItem in project.AllEvaluatedItems.Cast<ProjectItem>().Where(item => item.ItemType == "Compile"))
{
var filePath = compileItem.EvaluatedInclude;
...
}
I checked the msbuild github repository - it does not use the NuGet packages either. Instead it includes the source code for all the relevant libraries and just builds them. And these dlls work too just as the VS dlls work.
So, what is the deal with the NuGet packages? I do not get it. Opened https://github.com/dotnet/msbuild/issues/6147