MSBuildWorkspace无法编译具有<ProjectReference>到另一个项目的项目。

7

请注意,我还在 Roslyn 的 GitHub 上提出了这个问题(附有重现代码)链接

  • 创建一个包含 2 个项目(CoreLibrary 和 DownstreamLibrary)的新解决方案。
  • 从 DownstreamLibrary 向 CoreLibrary 添加项目引用。
  • 运行以下代码并注意 DownstreamLibrary 不再编译。

请注意,我尝试将 net461、netcoreapp2.1 和 netstandard2.0 作为项目的目标框架 - 每次都遇到相同的问题。

static async Task Main(string[] args)
{
    MSBuildLocator.RegisterDefaults();
    using (var workspace = MSBuildWorkspace.Create())
    {
        workspace.WorkspaceFailed += (sender, workspaceFailedArgs) => WriteLine(workspaceFailedArgs.Diagnostic.Message);
        var solution = await workspace.OpenSolutionAsync(@"c:\source\ForRoslynTest\ForRoslynTest.sln");
        WriteLine($"Loaded solution {solution.FilePath}");

        var projectTree = workspace.CurrentSolution.GetProjectDependencyGraph();
        foreach (var projectId in projectTree.GetTopologicallySortedProjects())
        {
            await CompileProject(workspace.CurrentSolution.GetProject(projectId));
        }
    }
}

private static async Task CompileProject(Project project)
{
    WriteLine($"Compiling {project.Name}. It has {project.MetadataReferences.Count} metadata references.");
    var compilation = await project.GetCompilationAsync();
    var errors = compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error);
    if (errors.Any())
    {
        WriteLine($"COMPILATION ERROR: {compilation.AssemblyName}: {errors.Count()} compilation errors: \n\t{string.Join("\n\t", errors.Where(e => false).Select(e => e.ToString()))}");
    }
    else
    {
        WriteLine($"Project {project.Name} compiled with no errors");
    }
}

您将收到以下输出:
Msbuild failed when processing the file 'c:\source\ForRoslynTest\DownstreamLibrary\DownstreamLibrary.csproj' with message: C:\Program Files\dotnet\sdk\2.1.602\Microsoft.Common.CurrentVersion.targets: (1548, 5): The "Microsoft.Build.Tasks.ResolveNonMSBuildProjectOutput" task could not be loaded from the assembly Microsoft.Build.Tasks.Core, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a.  Confirm that the <UsingTask> declaration is correct, that the assembly and all its dependencies are available, and that the task contains a public class that implements Microsoft.Build.Framework.ITask.

Found project reference without a matching metadata reference: c:\source\ForRoslynTest\CoreLibrary\CoreLibrary.csproj

Loaded solution c:\source\ForRoslynTest\ForRoslynTest.sln

Compiling CoreLibrary. It has 113 metadata references.
Project CoreLibrary compiled with no errors

Compiling DownstreamLibrary. It has 0 metadata references.
COMPILATION ERROR: DownstreamLibrary: 3 compilation errors:
        c:\source\ForRoslynTest\DownstreamLibrary\Class1.cs(1,7): error CS0246: The type or namespace name 'System' could not be found (are you missing a using directive or an assembly reference?)
        c:\source\ForRoslynTest\DownstreamLibrary\Class1.cs(5,18): error CS0518: Predefined type 'System.Object' is not defined or imported
        c:\source\ForRoslynTest\DownstreamLibrary\Class1.cs(5,18): error CS1729: 'object' does not contain a constructor that takes 0 arguments

所以我的问题是如何修复上述错误并使DownstreamLibrary编译?
编辑 我99%确定根本原因是以下错误
“Microsoft.Build.Tasks.ResolveNonMSBuildProjectOutput”任务无法从程序集Microsoft.Build.Tasks.Core,Version=15.1.0.0中加载
我已经确认使用procmon加载了以下DLL(C:\Program Files\dotnet\sdk\2.1.602\Microsoft.Build.Tasks.Core.dll),我已经使用ILSpy确认它不包含ResolveNonMSBuildProjectOutput任务。 旧版本的此DLL确实有此任务。

我发现,如果我将代码作为 .net 4.7.2 应用程序执行,而不是 netcoreapp2.1 应用程序,它可以正常工作。有什么想法吗? - RB.
所以,目前还没有明显的解决方案,这确实是您的错误报告中跟踪的一个错误吗? - ceztko
1
我们的应用程序现在以net472为目标,如我的评论所述。据我所知,MSBuildWorkspace不支持.NET Core(例如,参见此处)。 - RB.
1个回答

2
我找到了一个手动解决WorkspaceFailed错误的方法:

[错误] 处理时 Msbuild 发生失败,并显示以下消息:无法从程序集 Microsoft.Build.Tasks.Core、Version=15.1.0.0、Culture=neutral、PublicKeyToken=b03f5f7f11d50a3a 中加载“Microsoft.Build.Tasks.ResolveNonMSBuildProjectOutput”任务。请确认声明正确,程序集及其所有依赖项可用,并且该任务包含一个实现 Microsoft.Build.Framework.ITask 的公共类。

有几个解决步骤:
  1. 遵循 https://github.com/microsoft/msbuild/issues/4770,将 VS 2019 从 16.2 更新至 16.5.3... 这并没有解决我的问题,但值得记录。
  2. 我升级了我的 Microsoft.Build.* 和 Microsoft.CodeAnalysis 依赖项到最新版本,这还没有解决问题,仍然是同样的错误。
  3. 我进入了 C:\Program Files\dotnet\sdk 目录,之前在那里有几个目录:
1.0.0/                  1.0.0-rc4-004771/  2.0.3/    2.1.505/
1.0.0-preview1-002702/  1.0.3/             2.1.202/  3.1.100/
1.0.0-preview2-003121/  1.0.4/             2.1.4/    3.1.201/
1.0.0-preview4-004233/  1.1.0/             2.1.502/  NuGetFallbackFolder/

我将此重命名为sdk_o,并创建了一个新文件夹C:\Program Files\dotnet\sdk,只复制了3.1.201版本的内容。
成功了!这个错误已经消失了,但运行我的roslyn应用程序后出现了一些错误,如下所示(路径已删除)。
[Failure] Msbuild在处理该文件时失败,消息为"The "ProcessFrameworkReferences" task failed unexpectedly. System.IO.FileNotFoundException: Could not load file or assembly 'NuGet.Frameworks, Version=5.5.0.4, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. The system cannot find the file specified. File name: 'NuGet.Frameworks, Version=5.5.0.4, Culture=neutral, PublicKeyToken=31bf3856ad364e35'"
通过将NuGet.ProjectModel 5.5.1添加到我的项目中来解决这个问题,csproj现在具有以下包引用:
   <ItemGroup>
     <PackageReference Include="Microsoft.Build" Version="16.5.0" ExcludeAssets="runtime" />
     <PackageReference Include="Microsoft.Build.Framework" Version="16.5.0" ExcludeAssets="runtime" />
     <PackageReference Include="Microsoft.Build.Locator" Version="1.2.6" />
     <PackageReference Include="Microsoft.Build.Tasks.Core" Version="16.5.0" ExcludeAssets="runtime" />
     <PackageReference Include="Microsoft.CodeAnalysis" Version="3.5.0" />
     <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.5.0" />
     <PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="3.5.0" />
     <PackageReference Include="NuGet.ProjectModel" Version="5.5.1" />
   </ItemGroup>

这段代码再也不会出现WorkspaceFailed事件:

Microsoft.Build.Locator.MSBuildLocator.RegisterDefaults();
var workspace = MSBuildWorkspace.Create();
workspace.WorkspaceFailed += (s, e) => { Console.WriteLine(e.Diagnostic); };
var project = await workspace.OpenProjectAsync(@"C:/path/to.csproj");     

我正在使用Roslyn加载的csproj如下所示:
<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
      <TargetFramework>netcoreapp3.1</TargetFramework>
      <UseWindowsForms>true</UseWindowsForms>
      <OutputType>Library</OutputType>
      <ApplicationIcon />
      <StartupObject />
   </PropertyGroup>

   <ItemGroup>
      <ProjectReference Include="..\..\dependencies\some.csproj" />
   </ItemGroup>
</Project>

此外,这里还有文档:https://github.com/dotnet/roslyn/issues/36072#issuecomment-610809322 - Warty

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