Roslyn workspace API not loading properly for a third-party solution

80 Views Asked by At

I'm trying to enumerate all Document items in each Project instance using the Roslyn Workspace API for a third-party solution that has been provided to me. My code looks like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.MSBuild;


string slnPath = "ThirdPartySolution.sln";

MSBuildWorkspace workspace = MSBuildWorkspace.Create();
Solution s = await workspace.OpenSolutionAsync("ThirdPartySolution.sln")
);

foreach (Project p in s.Projects)
{
    Console.WriteLine(p.Name);
    Console.WriteLine(p.Documents.Count());
        
    foreach (Document d in p.Documents)
    {
        Console.WriteLine("\t" + d.Name);
    }
}

workspace.Dispose();

The code runs without errors when I build and run using .NET Core. Furthermore the names of the projects within this solution all appear to print out to the terminal. However, the count of Document instances in each Project object always turns out to be 0. I know this isn't the case, so I added the following code to try to diagnose the problem:

foreach (WorkspaceDiagnostic diagnostic in workspace.Diagnostics)
{
    Console.WriteLine(diagnostic.Message);
}

One of the diagnostic messages I'm getting is as follows:

The imported project "C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\amd64\Current\Microsoft.Common.props" was not found. Confirm that the expression in the Import declaration "C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\amd64\Current\Microsoft.Common.props" is correct, and that the file exists on disk.
C:\Program Files\dotnet\sdk\6.0.408\Sdks\Microsoft.NET.Sdk\Sdk\Sdk.props

I checked for the existence of the mentioned paths "C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\amd64\Current\Microsoft.Common.props" does not exist while C:\Program Files\dotnet\sdk\6.0.408\Sdks\Microsoft.NET.Sdk\Sdk\Sdk.props does exist.

I find this strange because the solution builds fine when I select the Buid > Build Solution item from the main menu in Visual Studio 2022. It also builds fine from the command line using msbuild.

What could be going wrong here?

Edit

Working solution:

// Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;

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

string slnPath = "ThirdPartySolution.sln";

MSBuildLocator.RegisterDefaults();

MSBuildWorkspace workspace = MSBuildWorkspace.Create();
Solution s = await workspace.OpenSolutionAsync(slnPath
);

foreach (WorkspaceDiagnostic diagnostic in workspace.Diagnostics)
{
    Console.WriteLine(diagnostic.Message);
}

foreach (Project p in s.Projects)
{
    Console.WriteLine(p.Name);
    Console.WriteLine(p.Documents.Count());
        
    foreach (Document d in p.Documents)
    {
        Console.WriteLine("\t" + d.Name);
    }
}

workspace.Dispose();

In addition to this, you have to make sure that ExcludeAssets="runtime" is set in your project file for all Microsoft.Build.* package references except for Microsoft.Build.Locator:

  <ItemGroup>
    <PackageReference Include="Microsoft.Build" Version="17.7.2"
        ExcludeAssets="runtime"/>
    <PackageReference Include="Microsoft.Build.Framework" Version="17.7.2"
        ExcludeAssets="runtime"/>
    <PackageReference Include="Microsoft.Build.Locator" Version="1.6.10" />
    <PackageReference Include="Microsoft.Build.Utilities.Core" Version="17.7.2"
        ExcludeAssets="runtime"/>
    <PackageReference Include="Microsoft.CodeAnalysis" Version="4.7.0" />
    <PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="4.7.0" />
  </ItemGroup>

Also check this link for more details.

1

There are 1 best solutions below

2
On BEST ANSWER

Currently (as of this writing in October 2023), you'll need to use the MSBuildLocator to register an instance of MSBuild before using MSBuildWorkspace. If you're trying to analyze a SDK style project you should also have your app be targeting .NET Core as opposed to .NET Framework.

I'm emphasizing the "currently" for the first part of this answer because I'm actually working on removing that requirement in this pull request so I would expect by the time the 4.9.0 NuGet packages ship, that'll no longer be a requirement and the user's original code should have just worked. So any future users of this quesiton, please check if that support is merged into the Roslyn build you're using.