代码改变世界

Assembly Manifest 通俗简易手册

2009-03-18 13:00  libiver  阅读(266)  评论(0编辑  收藏  举报

        Assembly Manifest 通俗简易手册

声明:此文章是在学习过程中转载,文章原文链接:http://hi.baidu.com/codinglife/blog/item/ea9acceab2f833d7d539c90e.html
无意侵犯作者版权,如有不妥,可联系leezhm@126.com本人将马上删除。

 

恩,为了大家都能很方便的理解,我将尽量简单通俗地进行描述。

[现象]

对这个问题的研究是起源于这么一个现象:当你用VC++2005(或者其它.NET)写程序后,在自己的计算机上能毫无问题地运行,但是当把此exe文件拷贝到别人电脑上时,便不能运行了,大致的错误提示如下:应用程序配置不正确,请重新安装程序……或者是MSVCR80D.dll 没有找到什么的(我记得不是很清楚,不过大致是这样的)

[分析]

看到这样的提示,当然不会傻到重装咯。第一反应应该是什么配置有问题、或者是缺少了什么依赖的库文件;于是我就根据以前Windows缺少库文件的经验,把所有库文件(××.DLL)统统一股脑地复制到当前文件夹下来,满心欢喜以为可以运行了,以运行……@#¥@#%¥……还是挂了。

[探索]

于是开始网上搜索,我Google,我摆渡;渐渐我发现,这一切都和一个叫做***.manifest 类型的文件发生关系,那么到底什么是 .manifest 文件呢?他有什么用,以前为什么没有?后来,经过艰苦努力,终于得知,原来这一切都是Windows 的Assembly Manifest搞的鬼。这个东东的作用就是为了解决 以前windows上的“Dll 地狱” 问题才产生的新的DLL管理解决方案。大家知道,Dll是动态加载共享库,同一个Dll可能被多个程序所使用,而所谓“Dll 地狱”就是当不通程序依赖的Dll相同,但版本不同时,由于系统不能分辨到底哪个是哪个,所以加载错了Dll版本,然后就挂了。于是盖茨就吸取了教训,搞了一个程序集清单的东东,每个程序都要有一个清单,这个清单存再和自己应用程序同名的.manifest文件中,里面列出其所需要的所有依赖,这儿所列出的依赖可不是简单地靠文件明来区分的,而是根据一种叫做“强文件名”的东西区分的,那么什么是强文件明呢?我们来看一下这个.manifest文件便知道了。

 

我们发现原来这是一个XML格式的文件,其中<dependency>这一部分指明了其依赖于一个名字叫做Microsoft.VC80.CRT的库。但是我们发现,<assemblyIdentity>属性里面还有其它的东东,分别是type系统类型,version版本号,processorArchitecture平台环境,publicKeyToken公匙(一般用来标示一个公司)……把他们加在一起便成了“强文件名”了,有了这种“强文件名”,我们就可以根据其区分不同的版本、不同的平台……总之,有了这种强文件名,系统中可以有多个不同版本的相同的库共存而不会发生冲突。[深入]恩,那么现在,我们就来具体了解一下这一套机制。首先是强弱文件名的问题。正如上面提到的那样,为了区分不同版本或不同厂商生成的相同的程序集,必须用一个Assembly Manifest程序清单来列出我这个程序集的强文件名--慢着,到这里你可能会问:刚才不是说Assembly Manifest程序清单是列出其所依赖的程序集的强文件名呢,怎么这里变成了当前文件的强文件明了呢?其实,Assembly Manifest程序清单有两部分功能,上面这个实例之所以标注了其所依赖的文件的强文件名是因为其是客户端的Assembly Manifest,在服务端有另外一个Manifest 来标注。

这个便是从WINDOWS/WinSxS/Manifests目录下取出来的一个manifest文件,再这个文件夹下有一陀子这种XML格式的manifest文件,其是服务端的程序清单。WinSxs是windows XP以上版本提供的[blue]非托管并行缓存(side-by-side catche)[/blue]里面安装了各种版本的经过强文件名签名的系统库,而上面这个文件<assemblyIdentity>正是标注了系统中Microsoft.VC80.CRT的一个版本的强文件名签名,如果其和客户端。.manifest 清单里面<dependentAssembly>所列出的依赖项对上的话,就会被加载。刚才说的side-by-side 是指各种不同的版本并行运行。上面这个服务端manifest文件中<file>标签具体指明了当前强文件名签名的到底是哪一个文件,其中还有这个文件的Hash签名,以确保文件的完整性。好了,有了这一套机制,就可以非常非常安全地进行库文件关联了,但是、但是貌似还有一个一直困扰我们的问题:这套机制安全是安全了,但是却失去了以前良好的前后版本兼容性,即如果你的系统库发生了升级,那么服务端的版本号发生了变化,那岂不是所有服务端程序都不能使用了吗?其实,windows还使用一个policy的策略文件来确认映射关系。