You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MSBuild从非packages路径复制NuGet依赖DLL致TeamCity构建失败

.NET Framework 4.6.2 项目跨环境构建时RuntimeInformation程序集加载失败问题

问题背景

  • 基于*.NET Framework 4.6.2*开发的C# WebApi应用,通过NuGet传递依赖引入System.Runtime.InteropServices.RuntimeInformation (v4.3.0),该包是Microsoft.CodeAnalysis.Razor 2.2.0、Microsoft.DotNet.PlatformAbstractions 2.1.0的自动安装依赖。
  • 本地环境构建的产物可正常运行,另一台机器上的TeamCity服务执行自动构建后,程序启动报错:Could not load file or assembly 'System.Runtime.InteropServices.RuntimeInformation, Version=4.0.2.0...'

初步排查结果

对比两侧构建产物、NuGet缓存文件后,确认存在以下差异:

  • 本地bin/debug目录下的System.Runtime.InteropServices.RuntimeInformation.dll文件版本为4.6.26011.1,修改时间为2021年8月10日,对应产物运行正常
  • TeamCity构建产物中同名dll文件版本为4.6.24705.1,修改时间为2016年5月11日,对应产物启动失败
  • 本地与TeamCity服务器的packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0目录下,NuGet包自带的dll版本均为4.6.24705.1,修改时间为2016年5月11日

初始疑问

  1. 本地packages目录下该dll版本为4.6.24705.1,为何构建输出到bin目录的版本为4.6.26011.1?MSBuild是否从packages以外的路径复制了该依赖?此前全盘搜索未找到本地存储的4.6.26011.1版本该dll。
  2. 如何监控MSBuild执行流程,定位本地构建时该dll被复制到bin/debug目录的具体来源路径?
  3. 如何调整引用配置,保证不同环境下构建的程序均可正常运行?

2022年6月21日进展更新

经排查确认,本地构建时该dll是从JetBrains Rider 2021.2.2自带的MSBuild扩展路径C:\Program Files\JetBrains\JetBrains Rider 2021.2.2\tools\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\net462\lib\复制到bin目录的,且仅该依赖取自该路径,暂不清楚MSBuild选用该路径的触发逻辑。

补充说明:项目引用了Kestrel等AspNetCore组件,同时适配.NET Standard 2.0,初步怀疑该问题与.NET Framework引用.NET Standard程序集时的构建扩展机制有关,已检索到同类问题反馈但暂未明确对应解决方案。

解决方案

MSBuild依赖来源定位方法

要定位构建时dll的复制来源,直接开启诊断级构建日志即可,不需要全盘搜索文件:

  • 执行构建命令时附加以下参数:msbuild [你的项目文件路径].csproj /t:Rebuild /v:diagnostic /fl /flp:logfile=build_detail.log
  • 构建完成后打开生成的build_detail.log,搜索System.Runtime.InteropServices.RuntimeInformation.dll,找到对应的Copy任务条目,会明确标注该文件的源路径、目标路径以及触发复制的判断逻辑,可100%定位文件来源。

你遇到的Rider扩展路径优先的问题,是.NET Framework引用.NET Standard 2.0程序集的默认构建机制导致的:
当MSBuild检测到项目依赖.NET Standard 2.0程序集时,会自动加载Microsoft.NET.Build.Extensions扩展,优先从扩展目录下复制适配当前.NET Framework版本、修复了跨框架兼容性问题的系统基础库,覆盖NuGet包中自带的旧版本,解决跨框架的类型转发、版本匹配问题。你本地Rider自带的扩展目录里是2021年更新的修复版dll,TeamCity构建节点用的是旧版MSBuild/Visual Studio Build Tools,没有对应版本的扩展文件,就回退到复制NuGet包里2016年的旧版dll,这个旧版本缺少正确的版本绑定配置,运行时找不到4.0.2.0版本对应的类型转发记录,就会抛出程序集加载失败的错误。

跨环境构建一致性修复方案

三个方案选一个即可,优先选择前两个,稳定性更高:

  • 方案1:统一构建环境版本(最稳妥)
    在TeamCity构建节点安装和本地开发环境版本一致的MSBuild/Visual Studio Build Tools,保证所有构建环境的.NET Build Extensions版本完全对齐,从根源上消除dll版本差异,不会引入额外的兼容性问题。
  • 方案2:显式固定依赖+配置绑定重定向
    • 不要依赖传递引用引入System.Runtime.InteropServices.RuntimeInformation,手动在项目中安装该包的4.3.0或更高稳定版本,显式指定引用版本号
    • 打开项目web.config,在<runtime>/<assemblyBinding>节点下添加该程序集的绑定重定向,也可以直接在项目属性中开启「自动生成绑定重定向」,让构建过程自动生成匹配的版本映射规则,参考配置:
      <dependentAssembly>
        <assemblyIdentity name="System.Runtime.InteropServices.RuntimeInformation" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
      </dependentAssembly>
      
  • 方案3:禁用扩展自动覆盖逻辑(不推荐)
    在项目.csproj文件的首个<PropertyGroup>节点下添加<DependsOnNETStandard>false</DependsOnNETStandard>,强制MSBuild不走Build Extensions的覆盖逻辑,所有系统依赖统一从NuGet包目录取。该方案需要全量回归测试所有.NET Standard相关依赖的加载逻辑,容易引入其他类型加载异常。

内容的提问来源于stack exchange,提问作者Jan Veselý

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 12:54:25