Microsoft.NET.Build.Extensions是什么?工作机制及MSBuild引用问题
- 本问题关联已发布的Stack Overflow问题:关联Stack Overflow问题
- Microsoft.NET.Build.Extensions是什么?
- 为何MSBuild构建时有时会从该路径加载引用,而非从项目本地
/packages文件夹获取NuGet包程序集?
现有一个面向*.NET Framework 4.6.2*的C#应用,引用了若干NuGet包,例如2.1.0版本的Microsoft.DotNet.PlatformAbstractions,该包依赖v4.3.0版本的System.Runtime.InteropServices.RuntimeInformation。NuGet已将对应dll下载到项目本地/packages文件夹,文件版本为4.6.24705.1。
本地构建时,该dll会被路径C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\net462\lib\System.Runtime.InteropServices.RuntimeInformation.dll下版本为4.6.26011.1的更高版本同名文件覆盖,本地构建后的程序运行正常。
但构建服务器的MSBuild目录下不存在Microsoft.NET.Build.Extensions文件夹,尽管构建显示成功,最终生成的程序从/packages文件夹复制了4.6.24705.1版本的低版本对应dll,运行时抛出错误:
Could not load file or assembly 'System.Runtime.InteropServices.RuntimeInformation ...'
经排查,MSBuild\Microsoft\Microsoft.NET.Build.Extensions文件夹是通过Visual Studio Installer为Visual Studio Build Tools 2019安装**.NET SDK**时生成的,相关配置截图如下:
安装.NET SDK后,构建流程会识别该路径,构建时部分System类库会被该路径下的文件覆盖。经推测该机制可能与*.NET Standard*兼容性相关,需要明确该场景下MSBuild构建流程的具体工作逻辑。
Microsoft.NET.Build.Extensions是.NET SDK附带的兼容支持组件,核心作用是为面向旧版.NET Framework的项目提供.NET Standard/.NET Core类库的版本统一与类型转发能力,解决不同NuGet包依赖不同版本基础运行库导致的加载冲突问题。- 当构建环境安装了对应版本的.NET SDK和构建扩展组件时,MSBuild会按如下逻辑执行:首先正常解析所有NuGet包依赖,在将依赖文件复制到输出目录之前,会自动将所有.NET基础运行时类库(如
System.Runtime.InteropServices.RuntimeInformation这类System命名空间下的基础类库),替换为扩展目录下经过官方兼容性测试的版本。该替换逻辑与项目目标框架版本绑定,例如面向net462的项目,会自动匹配读取扩展路径下net462/lib子文件夹中的对应dll。 - 构建服务器出现运行报错的核心原因是服务器环境未安装对应版本的.NET SDK,缺少这套扩展组件,MSBuild无法执行基础库版本统一步骤,直接将NuGet缓存中的低版本dll复制到输出目录。该低版本dll缺少必要的类型转发配置和功能补丁,运行时会触发程序集加载失败错误。
- 标准修复方案:在构建服务器的Visual Studio Build Tools安装配置中,勾选对应版本的.NET SDK组件,确保
Microsoft.NET.Build.Extensions目录存在即可。如果不便调整服务器环境,也可以手动在项目配置中添加程序集绑定重定向规则,指定运行时加载正确版本的基础库,不过安装对应SDK组件是官方推荐的方案,兼容性与稳定性更有保障。
内容的提问来源于stack exchange,提问作者Jan Veselý

