c# - 使用 MSBuildWorkspace 加载解决方案和项目时出现诊断错误

标签 c# .net roslyn .net-core-3.1

我正在尝试使用 Roslyn 编译器在 .Net Core 中编写一个类来编译我的项目并返回该项目中的 ClassDefinitions。我将使用该信息通过 T4 生成代码。

这是一个 .Net Core 3.1 项目。

我找不到任何关于应该使用哪些包来完成此任务的良好文档。

在加载解决方案后,在解决方案 getter 中,我在 Documents 属性中没有收到任何文档,并且它尝试加载的每个项目都收到 1 条诊断消息:

System.ApplicationException: 'Msbuild failed when processing the file 'C:\Projects\FB-IT\grouptool\sources\Wur.Grouptool\Wur.GroupTool.Web\Wur.GroupTool.Web.csproj' with message: The SDK resolver type "WorkloadSdkResolver" failed to load. Could not load file or assembly 'System.Runtime, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.  C:\Projects\FB-IT\grouptool\sources\Wur.Grouptool\Wur.GroupTool.Web\Wur.GroupTool.Web.csproj
Msbuild failed when processing the file 'C:\Projects\FB-IT\grouptool\sources\Wur.Grouptool\Wur.GroupTool.Core\Wur.GroupTool.Core.csproj' with message: The SDK resolver type "WorkloadSdkResolver" failed to load. Could not load file or assembly 'System.Runtime, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.  C:\Projects\FB-IT\grouptool\sources\Wur.Grouptool\Wur.GroupTool.Core\Wur.GroupTool.Core.csproj
Msbuild failed when processing the file 'C:\Projects\FB-IT\grouptool\sources\Wur.Grouptool\Wur.GroupTool.Core.Tests\Wur.GroupTool.Core.Tests.csproj' with message: The SDK resolver type "WorkloadSdkResolver" failed to load. Could not load file or assembly 'System.Runtime, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.  C:\Projects\FB-IT\grouptool\sources\Wur.Grouptool\Wur.GroupTool.Core.Tests\Wur.GroupTool.Core.Tests.csproj
Msbuild failed when processing the file 'C:\Projects\FB-IT\grouptool\sources\Wur.Grouptool\Wur.Roslyn.Metadata\Wur.Roslyn.Metadata.csproj' with message: The SDK resolver type "WorkloadSdkResolver" failed to load. Could not load file or assembly 'System.Runtime, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.  C:\Projects\FB-IT\grouptool\sources\Wur.Grouptool\Wur.Roslyn.Metadata\Wur.Roslyn.Metadata.csproj
Msbuild failed when processing the file 'C:\Projects\FB-IT\grouptool\sources\Wur.Grouptool\Wur.Roslyn.Metadata.Tests\Wur.Roslyn.Metadata.Tests.csproj' with message: The SDK resolver type "WorkloadSdkResolver" failed to load. Could not load file or assembly 'System.Runtime, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.  C:\Projects\FB-IT\grouptool\sources\Wur.Grouptool\Wur.Roslyn.Metadata.Tests\Wur.Roslyn.Metadata.Tests.csproj
'

我安装了这些软件包(是的,甚至尝试了预发行版):

enter image description here

还必须在“排除 Assets ”属性中设置“运行时”:

enter image description here

这是我的类(class):

using Microsoft.Build.Locator;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.MSBuild;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Wur.Roslyn.Metadata
{
    public class RoslynProjectProvider
    {
        public string PathToSolution { get; private set; }
        public string ProjectName { get; private set; }

        public RoslynProjectProvider(string pathToSolution, string projectName)
        {
            PathToSolution = pathToSolution;
            ProjectName = projectName;
        }

        private MSBuildWorkspace _Workspace;

        public MSBuildWorkspace Workspace
        {
            get
            {
                if (_Workspace == null)
                {
                    MSBuildLocator.RegisterDefaults();

                    _Workspace = MSBuildWorkspace.Create();
                }

                return _Workspace;
            }
        }

        private Solution _Solution;

        public Solution Solution
        {
            get
            {
                if (_Solution == null)
                {
                    _Solution = Workspace.OpenSolutionAsync(PathToSolution).Result;

                    if(Workspace.Diagnostics.Count > 0)
                    {
                        StringBuilder sb = new StringBuilder();

                        foreach (var diagnostic in Workspace.Diagnostics)
                        {
                            sb.Append(diagnostic.Message).Append(Environment.NewLine);
                        }

                        throw new ApplicationException(sb.ToString());
                    }
                }

                return _Solution;
            }
        }

        private Project _Project;

        /// <summary>
        /// Singleton Project in a solution
        /// </summary>
        public Project Project
        {
            get
            {
                if (_Project == null)
                {
                    _Project = Solution.Projects.FirstOrDefault(p => p.Name.Equals(ProjectName, StringComparison.InvariantCultureIgnoreCase));

                    if (_Project == null)
                    {
                        throw new ApplicationException($"Cannot find project {ProjectName}");
                    }
                }

                return _Project;
            }
        }

        private Compilation _Compilation;

        /// <summary>
        /// Singleton compilation of the project
        /// </summary>
        public Compilation ProjectCompilation
        {
            get
            {
                if (_Compilation == null)
                {
                    _Compilation = Project.GetCompilationAsync().Result;
                }

                return _Compilation;
            }
        }

        private List<ClassDeclarationSyntax> _Classes;

        public List<ClassDeclarationSyntax> Classes
        {
            get
            {
                if (_Classes == null)
                {
                    _Classes = new List<ClassDeclarationSyntax>();

                    foreach (var document in Project.Documents)
                    {
                        var tree = document.GetSyntaxTreeAsync().Result;

                        var semanticModel = ProjectCompilation.GetSemanticModel(tree);

                        foreach (var type in tree.GetRoot().DescendantNodes().OfType<ClassDeclarationSyntax>())
                        {
                            _Classes.Add(type);
                        }
                    }
                }

                return _Classes;
            }
        }
    }
}

还有一个单元测试来测试该类:

public class UnitTest1
{
    [Fact]
    public void Test1()
    {
        var provider = new RoslynProjectProvider(@"C:\Projects\FB-IT\grouptool\sources\Wur.Grouptool\Wur.Grouptool.sln", "Wur.GroupTool.Core");

        var classes = provider.Classes;
    }
}

==编辑==

它要求版本5.0.0.0,但System.Runtime的版本较低。这可能是这里的问题吗?

enter image description here

==编辑==

Remark to first answer: Ok, got it working finally. Had to download the .Net Core 3.1.404 SDK from here: dotnet.microsoft.com/download/dotnet-core/thank-you/…. Added the path as you suggested and voila it started working.

它在单元测试中运行良好,但在 T4 模板中运行不佳。当我尝试运行自定义工具时,出现以下异常(启用绑定(bind)日志记录):

Severity    Code    Description Project File    Line    Suppression State
Error       Running transformation: System.IO.FileNotFoundException: Could not load file or assembly 'System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
File name: 'System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
   at Microsoft.VisualStudio.TextTemplating9A1960153A0EC5389F1AC1A553BA062D21024CF3A0BEA5F9915226007DBBA0457E39D7A79FF10F4293C4331881904FF0454986C06541AC3156F88310BB537850.GeneratedTextTransformation.TransformText()
   at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
   at Microsoft.VisualStudio.TextTemplating.TransformationRunner.PerformTransformation()

=== Pre-bind state information ===
LOG: DisplayName = System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 (Fully-specified)
LOG: Appbase = file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/
LOG: Initial PrivatePath = NULL
Calling assembly : Wur.Roslyn.Metadata, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in LoadFrom load context.
WRN: Native image will not be probed in LoadFrom context. Native image will only be probed in default load context, like with Assembly.Load().
LOG: Using application configuration file: C:\Users\User\AppData\Local\Microsoft\VisualStudio\16.0_966a030a\devenv.exe.config
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Post-policy reference: System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/System.Runtime/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PublicAssemblies/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PublicAssemblies/System.Runtime/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/System.Runtime/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/CommonExtensions/Microsoft/TestWindow/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/CommonExtensions/Microsoft/TestWindow/System.Runtime/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/CommonExtensions/Platform/Debugger/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/CommonExtensions/Platform/Debugger/System.Runtime/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/DataCollectors/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/DataCollectors/System.Runtime/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/DataCollectors/x86/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/DataCollectors/x86/System.Runtime/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/System.Runtime/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PublicAssemblies/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PublicAssemblies/System.Runtime/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/System.Runtime/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/CommonExtensions/Microsoft/TestWindow/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/CommonExtensions/Microsoft/TestWindow/System.Runtime/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/CommonExtensions/Platform/Debugger/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/CommonExtensions/Platform/Debugger/System.Runtime/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/DataCollectors/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/DataCollectors/System.Runtime/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/DataCollectors/x86/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/DataCollectors/x86/System.Runtime/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Projects/FB-IT/grouptool/sources/Wur.GroupTool/Wur.Roslyn.Metadata/bin/Debug/netcoreapp3.1/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Projects/FB-IT/grouptool/sources/Wur.GroupTool/Wur.Roslyn.Metadata/bin/Debug/netcoreapp3.1/System.Runtime/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Projects/FB-IT/grouptool/sources/Wur.GroupTool/Wur.Roslyn.Metadata/bin/Debug/netcoreapp3.1/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Projects/FB-IT/grouptool/sources/Wur.GroupTool/Wur.Roslyn.Metadata/bin/Debug/netcoreapp3.1/System.Runtime/System.Runtime.EXE.    Wur.GroupTool.Core.ViewModels   C:\Projects\FB-IT\grouptool\sources\Wur.GroupTool\Wur.GroupTool.Core.ViewModels\ViewModels\Web\PlayGround.tt    1

是否有可能只是因为它不存在而找不到它。我的目录中没有 4.2.2.0 版本:

enter image description here

最佳答案

SDK版本不匹配

看来,当您安装最新的 Visual Studio(我有 16.8.3)时 - MSBuildLocator 默认使用 .NET 5 MSBuild:

JsonConvert.SerializeObject(MSBuildLocator.QueryVisualStudioInstances(VisualStudioInstanceQueryOptions.Default)); 
// ouputs in VS 2019: 
// [{"Version":"5.0.101","VisualStudioRootPath":"C:\\Program Files\\dotnet\\sdk\\5.0.101\\","Name":".NET Core SDK","MSBuildPath":"C:\\Program Files\\dotnet\\sdk\\5.0.101\\","DiscoveryType":4}]
// just thought I'd try the same in LINQPad 5 and here's the output:
// [{"Version":{"Major":16,"Minor":8,"Build":30804,"Revision":86,"MajorRevision":0,"MinorRevision":86},"VisualStudioRootPath":"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community","Name":"Visual Studio Community 2019","MSBuildPath":"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\MSBuild\\Current\\Bin","DiscoveryType":2}]

当您执行MSBuildLocator.RegisterDefaults()时,它会从上面的列表中获取第一个实例。

然后,使用 .NET 5 MSBuild 加载 .NET Core 3.1 项目似乎会出现错误:

Msbuild failed when processing the file '...' with message: The SDK resolver type "WorkloadSdkResolver" failed to load. Could not load file or assembly 'System.Runtime, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.

但是,您可以告诉 MSBuidLocator 从特定 SDK 位置初始化环境:MSBuildLocator.RegisterMSBuildPath 。所以我尝试更新您的 Workspace getter,如下所示:

public MSBuildWorkspace Workspace
{
    get
    {
        if (_Workspace == null)
        {
            MSBuildLocator.RegisterMSBuildPath("C:\\Program Files\\dotnet\\sdk\\3.1.404");// your version might be different, check `dotnet --list-sdks`
            _Workspace = MSBuildWorkspace.Create();
        }
        return _Workspace;
    }
}

然后我必须遵循诊断输出并安装以下软件包:

<PackageReference Include="Microsoft.NET.HostModel" Version="3.1.6" />
<PackageReference Include="NuGet.Packaging" Version="5.8.0" />
<PackageReference Include="NuGet.ProjectModel" Version="5.8.0" />

将软件包安装到我的项目中后 - 我能够成功地在我的测试解决方案中列出类。

还有一件事

可能会让您绊倒的是缺少对 Microsoft.CodeAnalysis.CSharp.Workspaces 的引用(请参阅 this SO answer 了解更多背景信息)。

所以我最终像这样改变了你的构造函数:

public RoslynProjectProvider(string pathToSolution, string projectName)
{
    var _ = typeof(Microsoft.CodeAnalysis.CSharp.Formatting.CSharpFormattingOptions); // this line forces a reference so MSBuild loads the assembly in question.
    PathToSolution = pathToSolution;
    ProjectName = projectName;
}

我已将完整的工作示例发布到 GitHub如果您想查看一下,但它几乎是您打包在 VS 中运行的所有代码。

关于c# - 使用 MSBuildWorkspace 加载解决方案和项目时出现诊断错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65268617/

相关文章:

c# - 如何使用 Roslyn 将语句插入具有规范化空白的 block 中?

c# - "Model.member"和 "Html.TextBoxFor(m => m.member)"不同

c# - 为什么 C# 不支持泛型的泛型(具有参数化类型的泛型)?

c++ - 如何将参数传递给已经开始运行的线程

msbuild - 如何使用 roslyn 构建现有解决方案并解析 csproj 中的所有引用,以便我可以解析所有类型

c# - 使用 Roslyn 进行面向方面的编程

c# - C# 旋转函数的奇怪行为

c# - 根据基本实体的公共(public)标识符过滤相关实体

c# - 使用 MOQ 设置和返回的正确方法

c# - 带有 MySql 的 Log4net 不记录