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

时间:2018-10-26 14:57:44

标签: .net roslyn roslyn-code-analysis

对于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

Msbuild在处理文件'cusotom project.vbproj.or.csproj'并显示以下消息时失败:C:\ Program Files(x86)\ Microsoft Visual Studio \ 2017 \ Enterprise \ MSBuild \ 15.0 \ Bin \ Microsoft。 Common.CurrentVersion.targets:(1657,5):无法从程序集“ C:\ Program Files(x86)\ Microsoft Visual Studio \ 2017 \ Enterprise \ Common7 \ IDE \ CommonExtensions \ Microsoft \”中实例化“ GetReferenceNearestTargetFrameworkTask”任务NuGet \ NuGet.Build.Tasks.dll”。请验证任务程序集是使用与计算机上安装的版本相同的Microsoft.Build.Framework程序集构建的,并且您的主机应用程序没有缺少Microsoft.Build.Framework的绑定重定向。无法将类型为“ NuGet.Build.Tasks.GetReferenceNearestTargetFrameworkTask”的对象转换为类型为“ Microsoft.Build.Framework.ITask”的对象。

.NET 4.6.1 ,带有MSBUILD_EXE_PATH

在处理文件'cusotom project.vbproj.or.csproj'并显示以下消息时,Msbuild失败:C:\ Program Files(x86)\ MSBuild \ 14.0 \ bin \ Microsoft.Common.CurrentVersion.targets:(1407 ,5):无法从程序集“ Microsoft.Build.Tasks.Core,版本= 14.0.0.0,文化=中性,PublicKeyToken = b03f5f7f11d50a3a”中实例化“ AssignProjectConfiguration”任务。请验证任务程序集是使用与计算机上安装的版本相同的Microsoft.Build.Framework程序集构建的,并且您的主机应用程序没有缺少Microsoft.Build.Framework的绑定重定向。无法将类型为“ Microsoft.Build.Tasks.AssignProjectConfiguration”的对象转换为类型为“ Microsoft.Build.Framework.ITask”。

.NET Core 2.1

Msbuild在处理文件“ cusotom project.vbproj.or.csproj”时失败,并显示以下消息:找不到导入的项目“ \ bin \ Debug \ netcoreapp2.1 \ Microsoft。 .targets” 。确认声明中的路径正确,并且文件在磁盘上。 *

.NET Core 2.1 (带有MSBUILD_EXE_PATH)

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

我设置路径的方式:

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

我也尝试过按照某处的建议进行设置,但这并没有改变任何东西。

1 个答案:

答案 0 :(得分:1)

好,所以这里似乎有几件事在玩。

  1. 在调用MSBuildWorkspace.Create()方法之前,应将其配置为使用本地计算机上的特定msbuild配置。这是使用MEF解决所有必需的依赖项所必需的。看一下达斯汀·坎贝尔(Dustin Campbell)写的here的描述。

      

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

  2. 要在计算机上实际本地化msbuild实例,应使用辅助类MSBuildLocator,该类可在Microsoft.MSBuild.Locator nuget程序包(此处)中找到。

  3. 当前,实际上并没有真正支持在dotnet核心上运行整个过程。他们更新了上面指定的nuget软件包,以添加对dotnet core的支持(请参见this github issue),并且可以通过预览myget feed使用。