在NetCoreApp中使用Roslyn:未安装MSBuildWorkspace

时间:2017-04-08 02:06:06

标签: c# roslyn

我正在尝试学习如何使用Roslyn从c#源文件中提取信息。但我甚至无法开始,因为我似乎无法找到正确的方法来安装正确的软件包。

我正在尝试构建一个简单的netcoreapp1.1控制台应用。它的csproj文件如下所示:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp1.1</TargetFramework>
    <PackageTargetFallback>portable-net45+win8</PackageTargetFallback>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.CodeAnalysis" Version="2.0.0" />
    <PackageReference Include="Microsoft.Composition" Version="1.0.30" />
  </ItemGroup>

</Project>

我从在线阅读中看到,这足以加载任何包含MSBuildWorkspace的程序集......但显然不是。

如何正确配置项目?

2 个答案:

答案 0 :(得分:2)

不幸的是,MSBuildWorkspace is currently only supported on .Net Framework。您将无法从.Net Core中使用它。

答案 1 :(得分:1)

接受的答案似乎不再是最新的:存在一个支持.NET的 NuGet包 Microsoft.CodeAnalysis.Workspaces.MSBuild 核心控制台应用程序:

enter image description here

使用以下代码行尝试该软件包:

using Microsoft.CodeAnalysis.MSBuild;
...
var workspace = MSBuildWorkspace.Create();
var solution = workspace.OpenSolutionAsync(solutionFile.FullName).Result;

...它引发了异常。我发现有一个帖子(https://github.com/dotnet/roslyn/issues/17401#issuecomment-282605950),其中添加了其他一些似乎是依赖项的NuGet程序包。那在我的csproj中做了引用:

<PackageReference Include="Microsoft.Build" Version="16.7.0" />
<PackageReference Include="Microsoft.Build.Framework" Version="16.7.0" />
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="16.7.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.7.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.7.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="3.7.0" />

,有了这些参考,我就可以使用它了(我在Windows上工作)。

但是,我遇到了一个问题,即Microsoft.CodeAnalysis.Project的文档计数为0,而someProject.GetCompilationAsync()。Result.SyntaxTrees为空。未正确设置“ MSBUILD_EXE_PATH”(请参见https://github.com/dotnet/roslyn/issues/22415)。首先,我选择以这种方式设置最新的MSBuild.dll:

    private static void SetMSBuildPath()
    {
        var latestSdk = new DirectoryInfo(@"C:\Program Files\dotnet\sdk\").EnumerateDirectories().Where(f => Regex.IsMatch(f.Name, @"\d+\.\d+\.\d+"))
            .OrderByDescending(f => f.Name.Split(".")[0])
            .ThenByDescending(f => f.Name.Split(".")[1])
            .ThenByDescending(f => f.Name.Split(".")[2])
            .FirstOrDefault();

        Environment.SetEnvironmentVariable("MSBUILD_EXE_PATH", Path.Combine(latestSdk.FullName, "MSBuild.dll"));
    }

但是更好的方法是使用NuGet包Microsoft.Build.Locator,并在应用程序的开头调用它,如下所示:

MSBuildLocator.RegisterDefaults();

要执行此操作,请确保按照documentation的建议将MSBuild排除在您使用的Microsoft.Build.* NuGet软件包(Microsoft.Build.Locator除外)之外(这会更改上面显示的PackageReferences ):

<PackageReference Include="Microsoft.Build" Version="16.7.0" ExcludeAssets="runtime" />
<PackageReference Include="Microsoft.Build.Framework" Version="16.7.0" ExcludeAssets="runtime" />
<PackageReference Include="Microsoft.Build.Locator" Version="1.2.6" />
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="16.7.0" ExcludeAssets="runtime" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.7.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.7.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="3.7.0" />

PS:我没有研究过,但是也许https://github.com/daveaglick/Buildalyzer(NuGet软件包“ Buildalyzer”)解决了所有这些问题。