程序集引用不匹配0x80131040问题探究
进行插件式编程的时候,经常性地弹出这么个东西找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040),往往这种问题特别难以解决,搞定了一个还要出另外一个。得研究一下怎么处理。
引用不匹配
这里提示需要加载一个4.2.0.0版本的dll,我先看看文件夹下面有没有对应的dll,查看文件dll的详细信息。
这个版本号4.6.27818.1和4.2.0.0也差的有点太远了吧,是这个问题?其实不是的,这个地方显示的版本和程序集的版本不是一回事。
程序集版本
.NET程序有很多版本的说法,官方对这个有解释,通过文件管理器获得的版本是AssemblyFileVersion
,而程序集加载器定位的版本使用的是AssemblyVersion
,这两个东西完全不是一回事。通过右键,我们看不到AssemblyVersion,比较简单的方式,可以通过Powershell脚本来查看程序集版本。
ls *.dll -r |ForEach-Object {try {$_ | Add-Member NoteProperty FileVersion ($_.VersionInfo.FileVersion)$_ | Add-Member NoteProperty AssemblyVersion ([Reflection.AssemblyName]::GetAssemblyName($_.FullName).Version)} catch {}$_} |Select-Object Name,FileVersion,AssemblyVersion
可以看到,我这边的程序集是4.2.0.1版本的,不是4.2.0.0版本的,因此,程序集不能正常加载。
我自己的项目是使用nuget进行包管理的,引用的包的版本号是4.5.3(又多一个版本...),程序集版本是4.2.0.1。我找遍了整个项目,都没有找到我dll项目中关于4.2.0.0版本的引用,苦思良久,打盹的时候忽然想起来,是不是那个exe的问题?
绑定重定向
我的主exe程序是使用.NET Framework 4.6.1进行编译,然后单独编译dll作为插件放入一个文件夹,由exe程序进行加载。那有可能是exe引用了4.2.0.0这个版本,或者是其他dll插件引用了这个版本,造成版本不兼容。
这种情况可以有很多种解决方案,这篇文章写的非常详细,推荐读一读。而我这里使用了最简单也是作者比较推荐的办法,程序集引用的绑定重定向。
使用这个方法有一个前提,你需要完全了解其他程序引用这个程序版本的时候不会出问题,一般小版本号的变动,是相对比较安全的。
一直以来,我写.NET Framework程序貌似就很少有这种问题,是因为微软会自动给程序设置重定向,我们可以通过在项目上右键,点选自动生成绑定重定向。
之后,会出现一个app.config
文件,它会在生成程序的时候,变成程序名称.dll.config
的形式,里面大概是这个样子的:
<?xml version="1.0" encoding="utf-8"?>
<configuration><runtime><assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"><dependentAssembly><assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /><bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" /></dependentAssembly></assemblyBinding></runtime>
</configuration>
可以发现,这个东西对我们引用的版本内容进行了限制,强制某个范围内的版本重定向为一个固定的版本号。不过,虽然dll中已经有这个内容,但是exe不会理会它的,它只会看自己主程序的.exe.config文件。所以我们需要做的,就是把这一个部分内容搬到主程序的.exe.config
中。
修改后重新运行,然后有又提示找不到System.Buffers.dll了,如法炮制,问题解决。
Fusion Log
有时候,通过这个方法找下去,处理完了,也不一定能够解决,因为这个错误提示的是“未能加载文件或程序集或它的某一个依赖项。”,也可能是某个引用的依赖项出了问题,这样就不是很好找了。
好在.NET提供了一个程序集绑定日志的工具,可以帮助我们查看绑定的问题。一般情况下,这个东西是关闭的,系统会提示:
警告: 程序集绑定日志记录被关闭。
要启用程序集绑定失败日志记录,请将注册表值 [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD)设置为 1。
注意: 会有一些与程序集绑定失败日志记录关联的性能损失。
要关闭此功能,请移除注册表值 [HKLM\Software\Microsoft\Fusion!EnableLog]。
调试的话,可以打开这个注册表键值。或者简单点,直接使用Fuslogvw.exe
(程序集绑定日志查看器),用管理员账号启动,在设置中设置好记录的日志信息,然后就可以记录了,详细的使用方法,见这里。就能看到详细的信息了,可以帮助我们深入分析内部绑定的问题。(用完记得关,有性能损失。)
=== 预绑定状态信息 ===
日志: DisplayName = System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51(Fully-specified)
日志: Appbase = file:///C:/Temp/360zip$Temp/360$0/
日志: 初始 PrivatePath = NULL
调用程序集: DependencyWalker, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null。
===
日志: 此绑定从 default 加载上下文开始。
日志: 未找到应用程序配置文件。
日志: 使用主机配置文件:
日志: 使用 C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config 的计算机配置文件。
日志: 策略后引用: System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
日志: 相同的绑定已出现过,因 hr = 0x80070002 而失败。
Dependency Walker
说到dll的引用,就有必要提一提非常有名的一个工具Dependency Walker,它可以查看PE文件的引用情况,但是这个程序很久没有更新了,对.NET很不友好。我找了一下,发现几个替代:
- Dependencies
这个工具可以认为是Dependency Walker的升级版,可以查看PE文件的引用信息,对.NET也可以支持,不过看的信息太少了,也无法显示缺失的情况。
- DependencyWalker.Net
这个工具是专门为.NET设计的,可以查看程序集的引用情况,我删除了我插件的几个dll,然后看就是这个样子,一目了然,版本号也非常清楚。
通过这些工具,可以帮我们找一找到底是dll的问题,也许会对“试图加载格式不正确的程序。”、“引用不匹配。”等引用相关问题有所帮助。
这些工具处理的大多是静态引用,对于使用动态引用的,一般是不支持的。
总结
插件式编程极大增强了程序的拓展能力,不过,在处理程序集引用的时候,需要非常小心不同插件带来的引用问题。程序设计的时候,可以使用不同文件夹隔离不同的插件dll,并通过一些技巧来加载(可以查看之前的文章)和隔离,这样,就可以避免出现不匹配的错误了。
参考资料
- https://stackoverflow.com/questions/3267009/get-file-version-and-assembly-version-of-dll-files-in-the-current-directory-and
程序集引用不匹配0x80131040问题探究相关推荐
- 未能加载文件或程序集“*****.dll”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。(异常来自HRESULT:0x80131040)
未能加载文件或程序集"*****.dll"或它的某一个依赖项.找到的程序集清单定义与程序集引用不匹配.(异常来自HRESULT:0x80131040) 参考文章: (1)未能加载文 ...
- 未能加载文件或程序集“Newtonsoft.Json”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040)
未能加载文件或程序集"Newtonsoft.Json"或它的某一个依赖项.找到的程序集清单定义与程序集引用不匹配. (异常来自 HRESULT:0x80131040) 参考文章: ...
- 解决未能加载文件或程序集“Newtonsoft.Json ....“或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040)
解决未能加载文件或程序集"Newtonsoft.Json ...."或它的某一个依赖项.找到的程序集清单定义与程序集引用不匹配. (异常来自 HRESULT:0x80131040) ...
- 【转】[程序集清单定义与程序集引用不匹配]分析及解决
转自:https://www.cnblogs.com/shuangzimuchangzhu/p/8572817.html 什么是程序集清单(Assembly Manifest)? 我们知道,在.net ...
- 找到的程序集的清单定义与程序集引用不匹配
我试图在C#Windows窗体应用程序(Visual Studio 2005)中运行一些单元测试,但出现以下错误: System.IO.FileLoadException:无法加载文件或程序集&quo ...
- 关于 未能加载文件或程序集“”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 的解决办法
这是C#中经常遇到的一个问题'未能加载文件或程序集""或它的某一个依赖项.找到的程序集清单定义与程序集引用不匹配. ',最常见的错误原因是:config配置文件里面声明的dll版本 ...
- C#找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040)”
问题描述:这是在C#为后端遇到的一个问题,我在w3wp进程下调试的时候一个引用报了 这个异常. 查阅半天过后,大概了解到这是由于dll文件引用不匹配造成的. 解决方案:当你在管理工具里引用或者更新了新 ...
- System.IO.FileLoadException:“未能加载文件或程序集“xxx”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配
原因分析:方法对应的程序集所引用组件对应的dll文件与项目文件XXX.csproj中记录的Version,PublicKeyToken等信息不对应 <Reference Include=&quo ...
- 【Bug】找到的程序集清单定义与程序集引用不匹配
问题 什么是程序集清单(Assembly Manifest) 我们知道,在.net中.程序是以程序集为单位进行打包的,通常一个.exe文件或一个.dll文件就是一个程序集.程序集一般包含了以下几个部分 ...
最新文章
- 用awk数组处理两个文件的例子
- javascript高级程序设计pdf_一个老牌程序员推荐的JavaScript的书籍,看了真的不后悔!...
- 页面浏览事件之 $AppViewScreen 全埋点
- vim 折叠的用法
- boost::fusion::extension::adt_attribute_proxy用法的测试程序
- c++ 获取linux系统信息_linux系统c程序移植
- ASP.NET网站性能提升的几个方法
- 浅谈 EF CORE 迁移和实例化的几种方式
- 北航教授李波:说AI会有低潮就是胡扯,这是人类长期的追求
- Vmware安装red hat linux及VMware tools
- OSPF协议配置命令解析
- 跨域组播--MBGP+MSDP+Anycast RP
- 【历史上的今天】11 月 8 日:为开源献身的互联网之子;卷积神经网络 LeNet-5 问世;特斯拉发明遥控器
- python拦截广告弹窗_通过python实现弹窗广告拦截过程详解
- android 应用市场图尺寸,【干货】最新App应用市场截图尺寸大全
- Laravel 学习笔记: 授权策略(Policy)
- Android 跨平台技术对比
- 基于时空注意力的图卷积网络在路段级交通预测中的应用
- 阅读笔记(Every Document Owns Its Structure: Inductive Text Classification via Graph Neural Networks)
- 我的2020年度总结 “既往不恋,纵情向前”
热门文章
- Java内功心法,创建型设计模式包括哪些
- [Mysql] 聚集函数:NULL是否包含在内(包括count(1)和count(*)的比较)
- 尽收眼底,3款常用的PC端软件,简洁实用又良心
- STM32串口发送接收数据
- 编程工具:检测永真永假分支
- 根据模板导出word,复合格式表格生成、可变列表格生成
- .net core通过PinYinConverterCore实现汉字转拼音,获取中文字符串首字母
- 女硕士患绝症谱写生命绝唱 参加答辩1月后辞世
- (二十二)岁月无声 - 8
- psql切换schema_PostgreSQL 模式(SCHEMA)