如何使用Roslyn SDK编译.NET解决方案

3
对于多个(相当高级的)分析,我想使用Roslyn SDK: 1. 仅将诊断应用于“新”的代码(不包括过时的代码) 2. 检测死代码(适用于公共方法,定义应用程序的入口点) 3. 大批量代码修复
换句话说:仅在Visual Studio中构建和应用DiagnosticAnalyzer是不够的。我已经成功构建了这些,并为它们编写了单元测试(受Sonar启发)。但是,那只分析了一个(或最多几个)文件。
所以这是我的问题:我尝试了几种加载完整的.NET解决方案并编译它(自己),但都失败了。
public static async Task Main(string[] args)
{
    var analyzers = (new DiagnosticAnalyzer[] { new MyCustomAnalyzer }).ToImmutableArray();

    var file = new FileInfo(@"c:\path\my_solution.sln");

    using (var workspace = MSBuildWorkspace.Create())
    {
        workspace.WorkspaceFailed += OnWorkspaceFailed;

        var solution = await workspace.OpenSolutionAsync(solutionFile.FullName);
        var dependencyGraph = solution.GetProjectDependencyGraph();
        var projectIds = dependencyGraph.GetTopologicallySortedProjects();

        foreach (var projectId in projectIds)
        {
            using (var cancel = new CancellationTokenSource())
            {
                var project = solution.GetProject(projectId);

                var compilation = (await project.GetCompilationAsync(cancel.Token))
                    .WithOptions(project.CompilationOptions)
                    .WithAnalyzers(array, cancellationToken: cancel.Token);

                foreach (var diagnostic in await compilation.GetAllDiagnosticsAsync())
                {
                    (diagnostic.Severity >= DiagnosticSeverity.Error
                        ? Console.Error
                        : Console.Out).WriteLine(diagnostic);
                    // Do magic
                }
            }
        }
    }
}

这是我包含的软件包列表:

<PackageReference Include="Microsoft.Build" Version="15.8.166" />
<PackageReference Include="Microsoft.Build.Framework" Version="15.8.166" />
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="15.8.166" />
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="15.8.166" />
<PackageReference Include="Microsoft.CodeAnalysis" Version="2.9.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="2.9.0" />

我尝试过使用 .NET core 2.1 和 .NET 4.6.1 运行它(因为 Microsoft.CodeAnalysis.Workspaces.MSBuild 是针对 .NET 4.6.1 的)。我得到的错误如下(基于不同的设置):
.NET 4.6.1
当处理文件 'cusotom project.vbproj.or.csproj' 时,Msbuild 失败并显示以下消息:C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets: (1657, 5): "GetReferenceNearestTargetFrameworkTask" 任务无法从程序集 "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.Build.Tasks.dll" 实例化。请验证任务程序集是否已使用与安装在计算机上的 Microsoft.Build.Framework 程序集相同的版本构建,并且您的主机应用程序未缺少 Microsoft.Build.Framework 的绑定重定向。无法将类型为“NuGet.Build.Tasks.GetReferenceNearestTargetFrameworkTask”的对象强制转换为类型“Microsoft.Build.Framework.ITask”。
.NET 4.6.1 with MSBUILD_EXE_PATH
Msbuild在处理文件'cusotom project.vbproj.or.csproj'时失败,错误信息为:C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Common.CurrentVersion.targets: (1407, 5): "AssignProjectConfiguration"任务无法从程序集"Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"中实例化。请确认任务程序集已使用与安装在计算机上的Microsoft.Build.Framework程序集相同的版本构建,并且您的宿主应用程序未缺少Microsoft.Build.Framework的绑定重定向。无法将类型为'Microsoft.Build.Tasks.AssignProjectConfiguration'的对象强制转换为类型'Microsoft.Build.Framework.ITask'。

.NET Core 2.1

处理文件'cusotom project.vbproj.or.csproj'时,Msbuild失败,错误信息为:未找到导入的项目"\bin\Debug\netcoreapp2.1\Microsoft..targets"。请确认声明中的路径正确,并且磁盘上存在该文件。 *

.NET Core 2.1(使用MSBUILD_EXE_PATH)

处理'cusotom project.vbproj.or.csproj'文件时,Msbuild失败并显示以下消息:Program Files\dotnet\sdk..\Microsoft.Common.CurrentVersion.targets: (1544, 5): 无法从程序集Microsoft.Build.Tasks.Core, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a中加载"Microsoft.Build.Tasks.ResolveNonMSBuildProjectOutput"任务。请确认声明正确,程序集及其所有依赖项可用,并且该任务包含实现Microsoft.Build.Framework.ITask的公共类。

我设置路径的方式:

Environment.SetEnvironmentVariable("MSBUILD_EXE_PATH", @"Program Files\dotnet\sdk\..\MSBuild.dll");

我也尝试了使用“true”,因为在某个地方有人建议这样做,但是这并没有改变任何事情。

1
我认为这个问题可以帮到你。 - George Alexandria
1个回答

3

嗯,这里似乎有几个问题需要解决。

  1. 在调用MSBuildWorkspace.Create()之前,应该配置它使用你本地机器上的特定msbuild配置。这是为了使用MEF解析所有所需的依赖项。请查看Dustin Campbell写的说明 (此处)

    不要在应用程序输出中包含任何Microsoft.Build.*程序集,除了Microsoft.Build.Locator。如果你的应用程序包括Microsoft.Build.dllMicrosoft.Build.Framework.dllMicrosoft.Build.Tasks.CoreMicrosoft.Build.Utiltiies.Core,它们会干扰MSBuildLocator安装的程序集解析处理程序。

  2. 实际上,在你的机器上本地化msbuild,你应该使用一个帮助类MSBuildLocator,可以在Microsoft.MSBuild.Locator nuget软件包中找到(此处)。

  3. 目前,整个过程并没有真正支持在dotnet core上运行。他们更新了上述nuget软件包,以添加对dotnet core的支持(请参见此github问题),并可通过预览myget feed (此处)获得。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接