利用manifest文件对程序目录下的dll进行分类

1 背景

  对于大部分的券商和机构投资者,只能通过有交易所交易系统接入资质的券商提供的柜台系统来进行现货交易。相对于期货市场,现货市场的柜台系统千差万别,接入协议有明文字符串、二进制数据和FIX协议等,接入方式有TCP连接、COM组件和dll动态库等。要想开发一个覆盖市面上所有的现货柜台的报盘系统,就必须能同时支持这些柜台的所有接入方式。在开发的过程中遇到的关于动态库版本兼容问题有以下几个:

  1. 同一柜台系统提供商发布了2套柜台系统,用于对接这2套系统的开发包是一样的,只是由于版本不同不能通用
  2. 不同柜台系统提供的动态库包含了不同版本的第三方库文件(如libeay32.dll等)
  3. 部分券商对柜台系统进行了自定义开发,在柜台提供的开发包中加入了自己开发的动态库,以增加对接入授权的控制

  当系统中存在同名的且不同版本的动态库时,为了能方便管理和更新程序,只能对这些动态库进行分类整理。具体做法是在程序执行目录下对每个类别的柜台分别建立一个文件夹,用于存放对接该柜台所需要的所有的动态库文件。由于程序采用了静态加载的方式去加载dll,为了能让可执行文件在启动时能找到这些动态库,manifest文件就派上用途了。

2 关于manifest文件

  manifest文件是用于组织和描述并行组件或独立应用程序的xml文件。它主要包含了用于绑定和激活COM类、接口和库的相关信息,这些信息以往是存储在系统注册表中的[1]。在xp及以后的windows系统中,系统在执行EXE可执行文件时会首先读取Manifest文件,获得exe文件需要调用的DLL列表(此时获得的,并不直接是DLL文件的本身的位置,而是DLL的manifest),操作系统再根据DLL的Manifest文件提供的信息去寻找对应的DLL ,这样就可以区别不同版本的相同文件名的DLL文件[2]

微软msdn上的一个配图比较直观地描述了这一过程[3]

3 组件查找顺序

  在windows系统中,如果应用程序指定了组件依赖关系,则程序启动时首先在WinSxS文件夹中查找共享组件,若未找到,则在程序安装目录下查找私有组件。

  在大部分的情况下,组件的查找顺序如下所示:

  1. WinSxS 文件夹
  2. \\<appdir>\<assemblyname>.DLL
  3. \\<appdir>\<assemblyname>.manifest
  4. \\<appdir>\<assemblyname>\<assemblyname>.DLL
  5. \\<appdir>\<assemblyname>\<assemblyname>.manifest

更详细的描述可以查看msdn中的Assembly Searching Sequence

4 实现

场景一 程序需加载两个不同版本的sample.dll

解决办法:

  1. 分别建立两个文件夹(dlla,dllb),将两个不同版本的dll分别放入这两个文件夹
  2. 文件夹下分别新建一个manifest文件,文件名同文件夹名,例dlla.manifest、dllb.manifest
  3. 编辑manifest文件,内容如下(以dlla为例):
    1 <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    2   <assemblyIdentity name="dlla" processorArchitecture="x86" version="1.0.0.0" type="win32" />  <-- 这边的name必须为manifest文件所在的文件夹的名字
    3   <file name = "sample.dll"/>
    4 </assembly>

  4. 在需要用到动态库提供的函数的cpp中增加以下预处理指令(以dlla为例):
    1 // 指定加载dll的位置;
    2 #pragma comment(linker,"/manifestdependency:\"type='win32' "\
    3     "name='dlla' "\
    4     "version='1.0.0.0' "\
    5     "processorArchitecture='x86' "\
    6     "language='*' "\
    7     "\"")

重新编译后,程序便能正确找到指定的动态库了。

场景二 程序需加载两个不同版本的sample.dll,且不同版本的sample.dll分别又依赖不同的第三方开发库

解决办法:在场景一的解决办法的基础之上,在manifest文件中增加依赖的第三方库的信息,例:

1 <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
2
3   <assemblyIdentity name="dlla" processorArchitecture="x86" version="1.0.0.0" type="win32" />
4
5   <file name = "sample.dll"/>
6   <file name = "libeay32.dll"/>
7   <file name = "ssleay32.dll"/>
8
9 </assembly>

场景三 程序需加载两个不同版本的sample.dll,但是调用这2个动态库的代码存在某种引用关系。

解决办法:在这种场景下,由于预编译宏会互相覆盖,导致动态库不能正确加载,只能通过LoadLibrary的方式进行动态加载。事实上,通过动态加载可以加载任意路径的动态库,只是在使用方式上没有静态加载方便。

4 总结

利用manifest文件同时加载多版本的同名的动态库的方式是windows系统特有的功能,在平时c++的开发中也很少接触到。这边仅作记录供以后碰到相同问题的时候作为参考。

1. https://msdn.microsoft.com/en-us/library/aa375365(v=vs.85).aspx
2. http://blog.csdn.net/suxinpingtao51/article/details/42870937
3. https://msdn.microsoft.com/en-us/library/ff951640(v=vs.85).aspx

本文为原创内容,若有错误的地方烦请指正

本文地址:http://www.cnblogs.com/morebread/p/4953497.html

解决这个问题有两种办法:(办法一)在工程的 stdafx.h头文件里面加入如下代码行:#pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.VC90.CRT' version='9.0.21022.8' processorArchitecture='X86' publicKeyToken='1fc8b3b9a1e18e3b' language='*'\"")
(办法二)在工程里面设置,设置如下: (1)右键工程,打开工程的 Properties 属性页面。(2)展开  Configuration Properties 节点。(3)展开 Linker 节点。(4)选择  Manifest File 属性页。(5)在  Additional Manifest Dependencies 这一项里面填入如下内容:type='win32' name='Microsoft.VC90.CRT' version='9.0.21022.8' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b'以上两种办法都可以解决由于manifest 引发的问题,一般都是需要MFC的DLL库。

Win32 创建控件风格不是Win XP解决方案

(2011-05-23 17:25:21)

转载

标签:

style

manifest

有时候我有在用Win32 API来向窗体上添加控件时,通过CreateWindow或CreateWindowEx创建出来的控件的风格不像XP风格,而是像Windows 2000的风格,界面很难看。注意,是动态调用CreateWindow来创建控件,不是从资源中加载。

这种情况下,我们怎么办呢,通常说来,造成这种情况都是由于没有正确加载资源,我们知道,像button, combobox, listbox等这些控件都是放在comctl32这个DLL里面的,所以有时候在用这些系统自定义的控件时,需要我们首先调用InitCommonControlsEx函数。这个DLL的版本有很多,存放在Windows\winsxs目录下面,或者你直接检索:common control,结果如下:

好了,下面说一下解决方案吧:

这个根本办法就是加一个manifest文件,其内容如下:

      <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
     <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
     <assemblyIdentity
       name="XP style manifest"
       processorArchitecture="x86"
       version="1.0.0.0"
       type="win32"/>
         <dependency>
           <dependentAssembly>
             <assemblyIdentity
               type="win32"
               name="Microsoft.Windows.Common-Controls"
               version="6.0.0.0"
               processorArchitecture="x86"
               publicKeyToken="6595b64144ccf1df"
               language="*"
            />
           </dependentAssembly>
         </dependency>
      </assembly>

保存成一个后缀为:.manifest的文件,引入到.res文件中。

这样就行了。

还需要在资源文件中加一行:

       //
    1 RT_MANIFEST "TestCtrlStyle.manifest"

注意,有时候,加这样一句代码在资源文件中,链接时会出错:

1>Linking...
      1>CVTRES : fatal error CVT1100: duplicate resource.  type:MANIFEST, name:1, language:0x0409
      1>LINK : fatal error LNK1123: failure during conversion to COFF: file invalid or corrupt

这个错误是说工程中已经包括了RT_MANIFEST文件。那么此时,就不要加这句话,直接把这个.manifest文件加入到工程中就行了。

修改过后的界面如下:

上面这种方法是用manifest来设定引入的comctl32的版本,但注意上面的manifest,里面指定了这个comctl32的平台:processorArchitecture="x86",如果这个应用程序想在x64下面运行,就会导致一个问题:这个64位的程序链接的是32位的comctl32库,创建控件就会失败。所以最好的解决方案就是下面这种做法:

在头文件里面加入下面的语句:

#ifdef _UNICODE
#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_IA64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
#endif

这里就是根据编译选项来指定链接什么版本的库,这样编译出来的程序就不会有上述的问题。



manifestdependency,manifest文件相关推荐

  1. Manifest文件详解

    Manifest是个XML的描述文件,对于每个DLL有DLL的Manifest文件,对于每个应用程序Application也有自己的Manifest.对于应用程序而言,Manifest可以是一个和ex ...

  2. Rocksdb 写流程,读流程,WAL文件,MANIFEST文件,ColumnFamily,Memtable,SST文件原理详解

    文章目录 前言 Rocksdb写流程图 WAL 原理分析 概述 文件格式 查看WAL的工具 创建WAL 清理WAL MANIFEST原理分析 概述 查看MANIFEST的工具 创建 及 清除 MANI ...

  3. Android - Manifest 文件 详解

    Manifest 文件 详解 本文地址: http://blog.csdn.net/caroline_wendy/article/details/20899281 Manifest可以定义应用程序及其 ...

  4. 在Vista操作系统中通过manifest文件使VC应用程序获得管理员权限

    原文 VC编译出来的应用程序在vista下运行,有可能因为权限问题,不能成功运行. 用以下办法,给应用程序添加一个manifest文件,程序运行时系统就会跳出UAC对话框,获得管理权限. 1.打开应用 ...

  5. Android应用程序的组成部分和Manifest文件(转)

    Android应用程序由松散耦合的组件组成,并使用应用程序Manifest绑定到一起:应用程序Manifest描述了每一组件和它们之间的交互方式,还用于指定应用程序元数据.其硬件和平台要求.外部库以及 ...

  6. Teams的manifest文件开始支持多语言

    Teams发展速度飞快,Teams app的manifest文件schema也迎来了版本1.5,在这个版本里,很大的一个改进是支持多语言. 让我们一起来看看,如何在manifest文件里配置多语言. ...

  7. Microsoft Updater Application Block 1.5.3 服务器端manifest文件设计 [翻译]

    Microsoft Updater Application Block 服务器端manifest文件设计 译者:Tony Qu Manfest文件用于列出一次升级所需要的所有的文件,它与验证签名相关联 ...

  8. android动态更新配置文件,Android如何动态修改Manifest文件

    修改manifest文件Android Manifest.xml,添加相应的声明.在这里,我们需要将新定义的活动PrefsActivity注册到manifest文件. 同前面一样,在Eclipse中打 ...

  9. 智能一代云平台(四十):Maven项目如何将lib下依赖的包打印在manifest文件中

    强烈推荐一个大神的人工智能的教程:http://www.captainbed.net/zhanghan [前言] 今天突然发现在Pom文件中进行相关的设置,可以将自己所依赖的jar包在Manifest ...

最新文章

  1. feignclient url_Spring Cloud Feign 请求动态URL
  2. C语言有符号整数最小值,16位带符号整数为什么是
  3. GDCM:gdcm::IOD的测试程序
  4. 判断一个字符串是否包含另一个字符串(用java但是不能用index()这个函数)
  5. 层次聚类python实现_Python机器学习——Agglomerative层次聚类
  6. 信息学奥赛一本通 1043:整数大小比较 | OpenJudge NOI 1.4 05
  7. 推荐系统遇上深度学习(五)--DeepCross Network模型理论和实践
  8. 爬虫10-股票信息定向爬取
  9. Spring学习总结(26)——Spring事务原理详解
  10. TCP发送接收数据2
  11. oracle 取时间的日期函数,Oracle日期函数简介
  12. 【CSS 基础教程】
  13. 计算机审计风险背景,计算机审计风险探究
  14. Redis学习之hget命令
  15. Hrbust 2064 萌萌哒十五酱的宠物~(树链剖分+线段树)
  16. ElementUI 加载Loding组件
  17. 2019年的最新的最全的ava常见的面试题
  18. google map for Android
  19. 清理qmail邮件队列
  20. jQuery入门案例

热门文章

  1. SpringBoot——Banner介绍
  2. 网络层IP协议—ipv4
  3. 【Unity3D 常用插件】Haste插件
  4. BugKu -- AWD --S1排位赛-4
  5. origin 双Y轴堆积条形图
  6. php的strtoupper,关于PHP的strtoupper函数
  7. 华为云桌面---cloudclient安装使用
  8. 0x0000000000000000 in ??
  9. 计算机以一级上级模拟试题,计算机一级模拟试题带答案
  10. 汉诺塔(3塔、4塔思路详记)