首页 > 解决方案 > 如果未签名的 dll 的版本低于项目依赖项之一的要求,msbuild 拒绝复制它 - 这是设计使然吗?

问题描述

我有以下情况:

  1. 所有涉及的 dll 均未签名
  2. 解决方案中的所有项目都依赖于 Shared.dll 的 1.0.21221.1 版本
  3. 解决方案中某些项目的一些NuGet依赖依赖于同一个dll的1.0.21237.1版本。
  4. 构建 Web 应用程序时(让我们将其命名为Api),预计会将 Shared.dll 从文件夹复制$(OutDir)到该$(OutDir)_PublishedWebsites\Api\bin文件夹​​。中找到的 Shared.dll$(OutDir)版本为 1.0.21221.1。
  5. 未复制 Shared.dll,Web 应用程序无法运行。

这是来自二进制日志的证据:

图表 A - 版本冲突:

在此处输入图像描述

图表 B - ResolveAssemblyReference 指示不要复制 Shared.dll:

在此处输入图像描述

我知道 msbuild 不喜欢版本冲突的想法,但不复制 dll 会产生一个彻头彻尾的错误,因为应用程序无法启动。

我知道可以通过添加程序集绑定重定向来解决它。但我认为未签名的程序集没有必要。我理解错了还是我错过了什么?

编辑 1

以下是我对评论中发布的问题的回答:

(不幸的是我被要求混淆一些关键字,我不知道为什么)

  1. Api 项目究竟是如何引用 Shared.dll 的?

正如我们在展览中看到的那样,B Shared.dll 是 Api 的传递依赖项。实际上,Api 依赖于 Xyz.BusinessApi,如下所示:

<Reference Include="Xyz.BusinessAPI" />

现在 DLL 通过各自的 NuGet 依赖项依赖 Shared.dll,下面是 Xyz.BusinessAPI 的 project.assets.json 文件的片段: 在此处输入图像描述

  1. 还有哪些其他项目引用 Shared.dll 以及如何引用?

在 1.0.21221.1 版本中有很多项目将其作为 NuGet 包进行引用。问题是一些项目还引用了另外两个 NuGet 包,它们又依赖于同一个 NuGet 包的 1.0.21237.1 版本。这在 RAR 输出中显示 - 请参见附录A。

我想强调 - 没有项目将 Shared.dll 作为原始 dll 引用,只能作为 NuGet 包或通过其他 NuGet 或项目或项目 dll间接引用。项目 dll 是来自以前构建的解决方案的项目的 dll - 我们不允许项目引用其他解决方案,因此如果项目是在以前的解决方案中构建的,那么它将在后续解决方案中被引用为 DLL。

  1. 从 OutDir 复制到 _PublishedWebsites\api\bin 的机制是什么

这是_CopyFilesMarkedCopyLocal来自 C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Microsoft\VisualStudio\v16.0\WebApplications\Microsoft.WebApplication.targets 的标准 Web 应用程序发布目标:

    <!-- copy any referenced assemblies to _PublishedWebsites\app\bin folder -->
    <Copy SourceFiles="@(ReferenceCopyLocalPaths)"
          DestinationFiles="@(ReferenceCopyLocalPaths->'$(WebProjectOutputDir)\bin\%(DestinationSubDirectory)%(Filename)%(Extension)')"
          SkipUnchangedFiles="true"
          Retries="$(CopyRetryCount)"
          RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"/>
  1. Shared.dll 如何在 OutDir 中结束?

我们所有的代码都内置在共享的 bin 目录中——我们OutDir为所有项目设置了相同的值。因此,所有项目二进制文件及其依赖项,包括 Shared.dll 都首先出现在此处。

  1. binlog中是否有双重写入?

是的,但我认为它们不相关: 在此处输入图像描述

标签: msbuild

解决方案


简短的回答是您的项目间接依赖于 Shared.dll 的两个版本:1.0.21221.11.0.21237.1.

RAR(MSBuild ResolveAssemblyReference 任务)检查了所有 .dll 的所有引用并找到了这两个版本。它报告了一个冲突:

发生了冲突

注意它如何在方括号中报告 Shared.dll 21221 找到的文件路径,并为 21237 报告 [](表示未找到该版本的文件)。

There was a conflict under($rar)使用或搜索这些很有用$warning under($rar)

现在,OutDir 只包含 Shared.dll 21221,因此无法在任何地方找到版本为 21237 的 Shared.dll。

诀窍是搜索Shared.dll under($rar project(api.csproj))你会发现来自 RAR 的相关消息:

21221 不是 CopyLocal,21237 未找到

Considered "C:\Xyz\61\bin.link\Shared.dll",
        but its name "Shared, Version=1.0.21221.1, Culture=neutral, PublicKeyToken=null"
        didn't match the expected name "Shared, Version=1.0.21237.1, Culture=neutral, PublicKeyToken=null".

所以,它看到了冲突,决定统一在更高版本(21237)上,但没有找到那个版本的文件。所以 21221 的引用不是 CopyLocal 因为它没有在那个版本上统一,并且对 21237 的引用没有被解析,因为没有找到那个版本的文件。

要解决此问题,我建议添加对版本 21237 的 Shared.dll 的显式引用(通过 NuGet 或通过GeneratePathProperty包引用上的元数据:https ://docs.microsoft.com/en-us/nuget/consume-packages/ package-references-in-project-files#generatepathproperty)。如果您使用 GeneratePathProperty,则可以直接使用$(PkgFoo_Bar)\lib\net472\Shared.dll或类似方法引用 .dll。还要添加从 21221 到 21237 的绑定重定向以解决冲突。一旦正确的版本 (21237) 将在您的 OutDir 中,它将被正确复制到输出。

希望这可以澄清。


推荐阅读