Roslyn Workspace API加载第三方解决方案无法获取Document实例
我尝试使用Roslyn Workspace API枚举第三方解决方案中每个Project实例下的所有Document项,编写的代码如下:
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();
该代码基于.NET Core构建运行无错误,能正常打印解决方案中的项目名称,但每个Project对象的Document实例计数始终为0。
为排查问题,添加了诊断代码:
foreach (WorkspaceDiagnostic diagnostic in workspace.Diagnostics) { Console.WriteLine(diagnostic.Message); }
得到的诊断信息如下:
找不到导入的项目"C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\amd64\Current\Microsoft.Common.props"。确认导入声明中的表达式正确,且文件存在于磁盘上。
C:\Program Files\dotnet\sdk\6.0.408\Sdks\Microsoft.NET.Sdk\Sdk\Sdk.props
经检查,上述不存在的路径确实未找到,另一路径存在。但该解决方案在Visual Studio 2022中通过菜单构建和命令行msbuild构建均正常,请问问题出在哪里?
问题原因
出现此问题的核心原因是:Roslyn的MSBuildWorkspace默认会使用NuGet包中附带的MSBuild版本,而非本地Visual Studio安装的MSBuild环境,这导致项目文件在解析时出现路径错误,无法正确加载项目关联的文档资源。
修正方案
1. 完整可运行代码
需要引入Microsoft.Build.Locator并注册默认MSBuild实例,修改后的代码如下:
// 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"; // 注册本地安装的MSBuild实例 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();
2. 项目包引用配置
需确保项目文件中,除Microsoft.Build.Locator外,所有Microsoft.Build.*系列包引用都设置ExcludeAssets="runtime",避免与本地MSBuild环境冲突:
<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>
内容的提问来源于stack exchange,提问作者user32882

