.Net中DLL冲突解决(真假美猴王)

《西游记》中真假美猴王让人着实难以区分,但是我们熟知了其中的细节也不难把他们剥去表象分别出来。对问题不太关心的可以直接调到文中关于.Net文件版本的介绍

问题

最近在编译AKKA.net 时出现了一个问题:Newtonsoft.Json.dll 冲突.

C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Common.CurrentVersion.targets(1819,5): warning MSB3243: No way to resolve conflict between "Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed" and "Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed". Choosing "Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed" arbitrarily.

Consider app.config remapping of assembly "Newtonsoft.Json, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed" from Version "4.5.0.0" [C:\Program Files (x86)\Microsoft Visual Studio 12.0\Blend\Newtonsoft.Json.dll] to Version "7.0.0.0" [D:\TestProjects\GitHub\akka.net\src\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll] to solve conflict and get rid of warning.

解决

分析问题

在VisualStudio给出的错误提示中,第一句话着实让人摸不着头脑。还好第二句给出冲突Dll文件的具体路径。但是奇怪的的是明明通过以下命令:

获取的Newtonsoft.Json.dll 应该是 “7.0.1”版本,怎么出来让remaping 到 “7.0.0”版本。

奇怪啊!!

核实Nuget到Newtonsoft.Json.dll

打开Dll文件核实下:

双击“1 [Neutral]”图标,将会打开dll程序集的详细信息如下:

原来Assembly的确是“7.0.0.0”

那好吧,我们再来看下Blend 下的同名文件

 

Blend文件夹下的Newtonsoft.Json.dll

Assembly Version 4.5.0.0 这和上面7.0.0.0完全不一样啊,VisualStudio(VS)怎么会把他们混淆了??

尝试解决

让我们来猜下原因吧,那是不是VS找不到具体的7.0.0 的Dll呢,然后就找到了4.5.0 的DLL,结果就…??

打开报错的项目,先卸载项目,然后才可以编辑查看项目文件:

打开项目

 

发现有两个地方出现了Newtonsoft.Json :

在查阅过<choose>这个不常用节点的用法后,我猜这个是因为这个节点导致,于是直接Ctrl+H 替换成于Reference相同的路径,编译,成功通过

 

问题延续

三个重要的.Net 程序集版本

在.Net中有三个重要的版本信息,因为经常混淆,所以要大家注意:

// Assembly mscorlib, Version 2.0.0.0
[assembly: AssemblyFileVersion("2.0.50727.3521")]
[assembly: AssemblyInformationalVersion("2.0.50727.3521")]
[assembly: AssemblyVersion("2.0.0.0")]

版本信息的四部分,我们约定为Major Version(主版本), Minor Version(次版本), Build(编译版本), and Revision(修订版本)

AssemblyFileVersion

通常我们会手动设置 AssemblyFileVersion 中的Major和Minor 去体现程序集的版本,Build 和(或者) Revision 这两个一般是由Build工具在每次编译程序集时自动增加的。 我们可以用AssemblyFileVersion来作为程序集的唯一标识。(调试的时候我们就可以根据这个版本号找到相应dll,)

 

在项目开发中一般我们会用ChangeList(变更集)号去生成AssemblyFileVersion 的Build和Revision两部分。这样就很方便从dll找到相应的源代码变更集。省去了自己单独去记录发布的dll和源代码对应关系的繁琐事项。

AssemblyFileVersion 存储在Win32的版本资源中,所以可以通过资源浏览器(右击属性)查看程序集的相应AssemblyFileVersion

The CLR does not care about nor examine the AssemblyFileVersion.

AssemblyInformationalVersion

AssemblyInformationalVersion 目的是用于整个产品(某个dll或者exe)能够有一个一致的(coherent)版本。这个产品可能含有很多个程序集,而且这些程序集可能有不同的版本标识策略或者根本不是同一个团队开发的。

“For example, version 2.0 of a product might contain several assemblies; one of these assemblies is marked as version 1.0 since it’s a new assembly that didn’t ship in version 1.0 of the same product. Typically, you set the major and minor parts of this version number to represent the public version of your product. Then you increment the build and revision parts each time you package a complete product with all its assemblies.”

        — Jeffrey Richter, CLR via C# (Second Edition) p. 57

 

The CLR does not care about nor examine the AssemblyInformationalVersion.

AssemblyVersion

AssemblyVersion 存储在AssemblyDef的元数据列表清单,任何引用该AssemblyVersion 版本的dll(.exe)。

The AssemblyVersion is used by the CLR to bind to strongly named assemblies.(CLR唯一关心的版本)

这一点至关重要,只有AssemblyVersion版本完全一致的(匹配的)强命名程序集,才能编译成功。例如,如果你引用了一个1.0.0.0的强命名A.dll,编译后,你将A.DLL升级到了1.0.0.1.那么,不好意思,你的程序将会失败,那就没有办法了吗?有可以参考Assembly Binding Redirection 来做DLL重定向。

 

小心修改AssemblyVersion

当别的开发人员正在引用你发布的程序集是,你应该非常小心的去修改这些程序集的AssemblyVersionAssemblyVersion的任何改动都意味着开发者不得不重新编译应用程序(或者相应的dll)而不是简单的直接文件覆盖(新版本dll直接覆盖就版本dll)。

  • 如果要保证当前发布的dll向后兼容,请不要修改AssemblyVersion。
  • 如果你有突破性的修改(脱胎换骨的大改动),那请修改AssemblyVersion。

 

总结

有的同仁总觉得.Net简单,GC帮我做了好多内存管理工作,我们就可以随心所欲,为所欲为。且不知任何技术都有他不可告人的软肋,广告总是大篇幅的说着自己的完美哪有功夫给大家展示自己的不足(当然这里很多时候涉及到了设计准则哲学,如框架设计会优先考虑20%的经常使用功能,而暂缓考虑其他的80%不常用的功能)。

所以学习一门技术一定要知道他的底层原理和关键点。知道的越多,你被坑的概率就会越少,效率就越高。

 

参考

Newtonsoft.Json Assembly Conflict

Choose Element (MSBuild)

Assembly Versioning in .NET

Assembly Binding Redirection

《CLR Via C#》

时间: 2024-08-26 14:00:39

.Net中DLL冲突解决(真假美猴王)的相关文章

.Net中DLL冲突解决 【转帖】

转自:http://www.cnblogs.com/HQFZ/p/5000038.html 最近在编译AKKA.net 时出现了一个问题: Newtonsoft.Json.dll 冲突. C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Common.CurrentVersion.targets(1819,5): warning MSB3243: No way to resolve conflict between " Newtonsoft.Js

[BetterExplained]亲密关系中的冲突解决

一般来说,解决冲突的办法是两人都不越界要求对方,尊重对方的意愿,但一旦双方皆认为自己合理,冲突却不可避免的时候,就必须各自退回到尊重对方的自由. 但其实这也不是问题的终极解决之道,因为这会导致一旦冲突发生,两人就退回到自己的领地,制造出冷战气氛来,“尊重对方”说起来容易,做起来着实没有那么容易. 这里有一个更好的方案,简言之就是两人都将双方看成一个利益共同体. 现实生活中人们其实很难将他人的利益真正放在心上,不过亲密关系中的人如果想最优化相处的话还必须得这么做,因为本身两人的利益就是一个整体.

团队开发中Git冲突解决

正常来说我们团队协作开发过程中,冲突是常有的事,下面介绍下本人在开发中的解决办法. 冲突的主要原因就是由于我们开发人员在分支的同一位置写入了不一样的代码,然后合并到主干上导致我们冲突. 方法: 当冲突发生时,我们可以选中冲突的代码 ---->点击鼠标右击 ---->Compare with ----->HEAD Revision进行两个窗口的代码比较即可,删除冲突的代码即可 解决冲突办法:删除冲突的代码,然后在add to index就可以了,然后我们在commit提交到本地即可.

eclipse中svn冲突解决

Eclipse中的svn冲突解决办法: 1. 点击提交,报错——‘SVN提交’has encountered a problem. 2. 选中无法提交的文件,点击更新操作.多出三个文件,分别是:“.mine”“r(xxx+1)”“r(xxx)”其中xxx为版本号.“.mine”是我要提交的文件,“.r(xxx)”是我是在这个版本文件基础上修改后产生冲突的.“r(xxx+1)”是目前svn服务器最新版本的内容是这样. 3. 我们通过手动处理源文件“.java”,得到自己真实想要上传到svn的文件后

git在idea中的冲突解决(非常重要)

1.什么是冲突 冲突是指当你在提交或者更新代码时被合并的文件与当前文件不一致.读起来有点绕,结合下面的案例理解. 从上面对冲突的定义来看,冲突时发生在同一个文件上的. 2.生产上冲突的场景 常见冲突的生产场景如下 更新代码 提交代码 多个分支代码合并到一个分支时 多个分支向同一个远端分支推送代码时 git的合并中产生冲突的具体情况: <1>两个开发者(分支中)修改了同一个文件(不管什么地方) <2>两个开发者(分支中)修改了同一个文件的名称 注意:两个分支中分别修改了不同文件中的部

Window phone应用中的多触点手势解读以及toolKit.dll和Microsoft.Phone.dll 冲突问题

我最近在在写一个windowphone应用,应用中有关于单点触控,多点触控的需要.如点击,双击,滑动,双指滑动等,在这个过程中遇到了一些问题,在这里分享一下我的心得. 首先对windowphone的触控的各种方法做一下总结分析,我对此处问题大部分来自一Charles Petzold先生的解读,在此对Charles Petzold先生表示感谢. 手势服务和侦听器 首先您需要安装 Windows Phone 7 开发工具,当然,还有 Silverlight for Windows Phone 工具包

三步快速解决dll冲突问题

最近在推广应用我们的分布式服务网关(Web Api):业务组大部分对外的业务逻辑以HSF服务或者自定义扩展插件的方式,注册并发布到分布式服务网关中,统一对外提供WebApi服务.临时介绍下我们的分布式服务网关: 1. 一键注册.发布WebApi服务, 2. 统一管理发布WebApi服务,实现WebApi的服务化治理 3. 集成安全认证.加解密.监控.日志等Aspect 4. 流量安全控制:流控 5. 横向伸缩.弹性扩展,支持大规模并发 6. 简化WebApi开发,提升开发效率,减少重复开发工作

Android中View类OnClickListener和DialogInterface类OnClickListener冲突解决办法

如下面所示,同时导入这两个,会提示其中一个与另一个产生冲突. 1 import android.view.View.OnClickListener; 2 import android.content.DialogInterface.OnClickListener; 其实,当我们用某个Listener时,不一定就要import它,直接用全名去定义就不需要import了,例如 1 mButton1.setOnClickListener(new OnClickListener() 2 { 3 4 @O

在启动php时,无法启动此程序,由于计算机中丢失MSVCR110.dll的解决方法

在启动php时,运行RunHiddenconsole.exe php-cgi.exe -b 127.0.0.1:9000 -c时,出现错误:无法启动此程序,由于计算机中丢失MSVCR110.dll 方法/步骤 首先进入 http://www.microsoft.com/zh-CN/download/details.aspx? id=30679 这个网址来进行相关程序的下载. 打开之后,在"选择语言"里选择"中文简体".然后点击右边的"下载"but