如何解决本地DLL 的PublicKey Token与项目需要的DLL的PublicKey Token不一致的问题

这个过程是这样的。有一个遗留的项目需要做一些修改,那么我就从TFS上把这个项目下载下来,用VisualStudio打开。编译时没有发现错误,直接运行。可是运行时就抛出了异常。

Could not load file or assembly 'log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821' or one of its dependencies.
The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)":"log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821"}

我的第一反应是这个Log4Net.dll找不到,觉得那么在reference列表中这个dll应该是黄色才对。右键查看项目引用的dll,发现Log4Net.dll正常引用,并没有黄色叹号,说明找到了这个dll.(后来想想也对,如果有黄色叹号标记的dll,那么说明找不到这个dll,那么编译的时候就应该报出异常,说找不到这个dll,所以由此总结,带黄色叹号的都是项目要用到的,但是没有在本地找到的,编译不会通过。如果没有黄色叹号抛出上边的异常,那么就是这个dll找到了,但是可能版本不一致。)

双击reference列表中的Log4Net.dll,可以看到其详细的信息,可以看出,这个dll指向的路径是GAC中,那么我就去GAC中找,确实在我本机找到了。

这个程序集存在于GAC中。那么我们查看一下这个Log4Net的dll信息。

果然,这里的publicKey Token与所需要的PublicKeyToken=1b44e1d426115821不一致。那么怎么解决这个问题?以前记得解决DLLversin不一样问题的时候,可以使用web.config或者app.config中的runtime节点进行redirect映射,那么publicTokenKey 可以吗?我找了找,没有找到相关配置。怎么办? 那么就去找指定publicKey token的dll吧。去哪里找?去Log4Net的官网找。确实,官网说明了它的dll变过publicKey
token.

不过一般来讲,一个公司发布产品类型的dll,本不应该变换publickey Token签名的,否则会给用户带来像本文提到的这种问题,不同的人机器人可能安装了不同publickeytoken的签名版本,造成混乱。但是不知道为什么Log4Net却中途变了这个签名,有newkey与oldkey版本。

我下载了new key的版本,觉得这个应该是项目需要的,但是怎么确定一下这个下载来的dll的publickkeytoken呢?这里就可以用VS自带的工具。打开VS命令行,输入sn命令就可以。

由此可以看到这个publickey token不是。所以继续下载了oldkey的dll,使用同样的方法,最终证实确实是需要oldkey的版本。所以,我下载下来这个Log4Net.dll,然后在项目中建立一个Lib目录,把dll放进去,让项目对其添加引用。publickeyToken对了,此时我们需要看一下,那么版本对吗?右键查看这个新引用的dll的property,发现版本还真不对。项目需要Version=1.2.10.0,而这个新下载的是1.2.13.0,那么怎么办?这时就可以用版本映射来解决了。打开配置问题件,在节点中增加这些信息,意思就是需要1.2.10.0的时候,如果遇到了1.2.13.0,那么就可以认为找到了对应的dll。

至此,编译运行,发现问题解决,没有再报任何的异常。

一些题外话:

以上的问题,都是由于项目开发时候的不规范造成的。像Log4Net这样的非微软集成到GAC中的dll,就应该在项目中建立一个Lib目录存储下来,以后当有人下载代码的时候,能够连带dll一起下载到本地,不用再大费周章的去找对应版本了。现在有时候是用Nuget就很好,那么额外的dll全会放到package中,并且include到项目中。

还有关于dll version的映射问题,这个不是什么时候都OK的。

比如说,现在我用到了一个第三方的dll,叫做SuperLog.dll,这个dll是一个公司的产品,这个公司是引用EntrepriseLogging.dll,引用的是5.0的版本,并且在这个基础之上增加功能。我们在一个项目中用到了SuperLog.dll,我们加入这个SuperLog.dll,编译时告诉我们需要引入EntrepriseLogging.dll,但是我们手头只有EntrepriseLogging.dll6.0的版本。或许我们可以引入6.0的版本,但是重新映射到5.0版本。但是,我们这样做了,编译的时候还是遇到了问题。异常好像是说,EntrepriseLogging没有某个方法之类的。所以,这个意思就是说,以前5.0的时候,可能有一个方法A(),正好被SuperLog调用了。但是在6.0版本的时候,EntrepriseLogging决定不要这个方法了。所以在我们项目中,虽然没有抛出版本不一样的异常,但是当把6.0的版本当5.0的用,对这个6.0版本掉用A方法,但是没有,就抛出了异常。

一般来讲,第三方DLL发布新的版本,基本上不会更新对外暴露的方法,只是会更新方法中的内容。所以,不管哪个版本我们用到的都是同一个方法。但是如果真的对外的方法都变了,增加了活减少了什么的,那么就会遇到上边的问题。所以,不是所有的版本不同问题都能通过配置映射来解决。

为什么要有PublickKey Token?

其中一个很重要的原因就是安全角度考虑。这样说吧,某公司开发了一个桌面程序A.exe,然后安装包供下载。你下载完成,并且安装。那么,在你的ProgramFile里边,就有A.exe与一些供其调用的dll,比如说B.dll,当你运行A的时候,会调用B.dll,完成相应操作。现在,如果有某个非法程序偷偷的跑到A的目录中,找到B.dll,然后把自己写的同名的dll替换原来的。这时运行A的时候,调用B,就可能会有一些恶意非法操作。PublicKey的作用之一就是用来验证B是否是完全一致的B。验证机制比较复杂,大家可以进一步探索。

时间: 2024-08-26 10:34:55

如何解决本地DLL 的PublicKey Token与项目需要的DLL的PublicKey Token不一致的问题的相关文章

解决本地tomcat服务器内存不足问题

2014-6-25 9:47:48 org.apache.coyote.http11.Http11Processor process严重: Error processing requestjava.lang.OutOfMemoryError: PermGen space 在server窗口,双击配好的server,点击openlaunch configuration  在 arguments 选项卡的VM arguments 的最后加上以下配置信息就好. -Xms256M -Xmx1024M 

关于git的ssh-key:解决本地多个ssh-key的问题

在设置github的时候,官方的说明文档要求备份当前的id_rsa,然后生成一份新的私钥用于github的登陆.如果真这样做,那么新的私钥是无法再继续登陆之前的机器的.这种方法有点暴力- 还好ssh可以让我们通过不同的私钥来登陆不同的域. 首先,在新增私钥的时候,通过指定不同的文件名来生成不同的私钥文件 ssh-keygen -t rsa -f ~/.ssh/id_rsa.work -C "Key for Work" ssh-keygen -t rsa -f ~/.ssh/id_rsa

PHP:phpMyAdmin如何解决本地导入文件(数据库)为2M的限制

经验地址:http://jingyan.baidu.com/article/e75057f2a2288eebc91a89b7.html 当我们从别人那里导出数据库在本地导入时,因为数据库文件大于2M而在phpMyAdmin导入时无法导入,主要原因是phpMyAdmin限制导入文件最大为2M,那么怎样解决呢? ******该方法为本地导入方法,虚拟主机的暂且不能******** 第一步,在PHP.ini配置文件中找到uplod_max_filesize,将默认的2M改为自己要导入文件的大小,如15

Node.js配合node-http-proxy解决本地开发ajax跨域问题

情景: 前后端分离,本地前端开发调用接口会有跨域问题,一般有以下3种解决方法: 1. 后端接口打包到本地运行(缺点:每次后端更新都要去测试服下一个更新包,还要在本地搭建java运行环境,麻烦) 2. CORS跨域:后端接口在返回的时候,在header中加入'Access-Control-Allow-origin':* 之类的(有的时候后端不方便这样处理,前端就蛋疼了) 3. 用nodejs搭建本地http服务器,并且判断访问接口URL时进行转发,完美解决本地开发时候的跨域问题. 用到的技术: 1

解决本地软件链接不上虚拟机mysql 的问题:grant all privileges on *.* to 'root'@'%' identified by 'nsfocus'

mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' ->     IDENTIFIED BY 'some_pass' WITH GRANT OPTION; //本地操作的权限 mysql> GRANT ALL PRIVILEGES ON *.* TO ' root '@'%' ->     IDENTIFIED BY 'some_pass' WITH GRANT OPTION; 首先要声明一下:一般情况下,修改MySQL

企业级分布式监控Zabbix部署+安装排错解决本地无法登录问题+测试邮件报警

---------------------概述---------------------- Zabbix是一个高度集成的企业级开源网络监控解决方案,与Caci. Nagios类似,提供分布式监控以及集中的Web管理界面.被监控对象只要支持SNMP协议或者运行Zabbix_agents代理程序即可,Zabbix的官方网址为http://www.zabbix.com/ 软件可以自由下载使用.补充:SNMP协议:简单网络管理协议(SNMP),由一组网络管理的标准组成,包含一个应用层协议(applica

VS2010 项目引用了DLL文件,也写了Using,但是编译时提示:未能找到类型或命名空间名称 <转>

昨天写了一个很小的winform程序,其中引用了自己写的两个dll文件. 本来认为轻松搞定,结果一编译居然提示:未能找到类型或命名空间名称..... 于是删掉两个dll重新引用,再编译结果依旧!很是郁闷. 后来经过调查,终于发现了解决方法: 在项目上点右键-->属性-->应用程序-->目标框架-->修改为.NET Framework 4. 而我原来的设置是.NET Framework 4 Client Profile.问题就出在这里. 以下是MSDN给出的提示: If you ar

转一篇DLL逆向的文章,适用于一般的dll逆向

转一篇DLL逆向的文章,适用于一般的dll逆向,我使用的库是一组DLL,都有强签名,如下方法不适合,编译会提示强签名错误. C# 带签名dll破解 Mar 9, 2016 | C# | 84 Hits 转自 http://blog.fwhyy.com/2016/03/csharp-with-signature-dll-crack/?utm_source=tuicool&utm_medium=referral 暂无评论 首先申明,本文只是从技术的角度来分析下怎样破解带签名的C#写的dll文件.大家

Aspnet前后端分离项目手记(二)关于token认证

在前后端分离的项目中,首先我们要解决的问题就是身份认证 以往的时候,我们使用cookie+session,或者只用cookie来保持会话. 一,先来复习一下cookie和session 首先我们来复习一下在aspnet中cookie和session的关系,做一个简单试验 这是一个普通的view没有任何处理 可以看到,没有任何东西(cookie),然后当我们写入一个session之后 \ 会发现多了一个名为ASP.NET_SessionId的cookie.我们都知道在aspnet中,session