




已阅读5页,还剩4页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
用vc如何获取某个动态链接库的版本信息我如何获得安装在我的系统上的某个特定的 DLL 的版本信息?我尝试着确定系统安装了哪个版本的 comctl32.dll。我见过有些代码调用 GetProcAddress 来获取各种函数,如 InitCommonControlsEx,以确定基于不同版本的函数调用。对于我来说,这是一个坎儿,到底用什么方法获得版本号? 有两种方法:容易的和难的。容易的方法是调用一个专门用于此目的的函数 DllGetVersion。问题是虽然 comctl32.dll 支持该函数,但并不是所有的 DLLs 都具备它。如果不具备 DllGetVersion,那么就得用难的方法使用 FileVersion API,这可能是你要遭遇到的最为暧昧的 API 之一。我写了一个类 CModuleVersion 来封装两种方法,同时还写了一个Demo程序 VersionDlg 来示范 CModuleVersion 的使用方法。程序画面如 Figure 1 所示。你可以在编辑框中敲入任何系统模块的名字,VersionDlg 将用 DllGetVersion (如果具备这个函数的话)和 FileVersion API 两种方法显示版本信息。源代码参见 Figure 2。 Figure 1 运行中的 VersionDlg 程序 让我们先看容易的方法。DllGetVersion 用 DLL 版本信息填写一个 DLLVERSIONINFO 结构。该结构定义在 Win32 SDK 的 showapi.h 头文件中。许多人可能都没有安装 Platform SDK,那么就得自己定义这个结构了(译者注:实际上,早期的 Developer Studio 不包含这个头文件。后来的 Visual Studio 6.0 安装已经包含该头文件,路经参见:Driver:Program FilesMicrosoft Visual StudioVC98Include),就像我在 VersionDlg 所做的那样。typedef struct _DllVersionInfo DWORD cbSize;DWORD dwMajorVersion;DWORD dwMinorVersion;DWORD dwBuildNumber;DWORD dwPlatformID; DLLVERSIONINFO;这个结构中的字段基本不用怎么说明就知道是什么意思:dwPlatformID 为 DLLVER_PLATFORM_WINDOWS (value = 1)指 Windows 9x,而 DLLVER_PLATFORM_NT (value = 2)用于 Windows NT。一旦定义了 DLLVERSIONINFO 结构,就可以调用 DllGetVersion 了,该函数的署名如下:HRESULT DllGetVersion(DLLVERSIONINFO*);因为并不是任何给定的 Dll 都输出 DllGetVersion 函数,你得按照标准套路来调用它,即调用 GetProcAddress 并判断返回值是否为 NULL。我编写的类 CModuleVersion 中含有一个 DllGetVersion 函数,它把所有细节都进行了封装(参见 Figure 2 中的 ModulVer.cpp。)CModuleVersion 类的使用方法如下:DLLVERSIONINFO dvi;if (CModuleVersion:DllGetVersion(comctl32.dll, dvi) / now info is in dviDllGetVersion 是一个比较新的函数(译者注:在1998年是这样。)对于 comctl32 很好使,因为它实现并输出 DllGetVersion但是对于那些不输出 DllGetVersion 的 DLLs 来说怎么办呢?例如:shell32.dll 就没有实现 DllGetVersion,如 Figure 3 所示。这时你就得用可怕以及奇怪的 GetFileVersionInfo 和 VerQueryValue 函数,它们在 winver.h 中定义。Figure 3 No DllGetVersion Info 大多数可执行程序和 DLLs 都具备 VS_VERSION_INFO 资源,在模块的 RC 文件中定义。Figure 4 是 VersionDlg 的 RC 文件中的版本信息。你可以用文本编辑器或者 Visual Studio 直接编辑资源文件中的这段信息。你可以指定文件版本,产品版本等等,以及任何你想要编辑的字段,如:CompanyName、InternalName。文件版本信息与 Exe 或 DLL 文件在资源管理器“属性”页“版本”标签中显示的信息相同(参见 Figure 5)。Figure 5 Version Tab 等一会儿你就会发现,这些版本 APIs 十分暧昧,很容易把人搞晕菜,但 CModuleVersion 使一切都变得简单明了。这个类派生于 VS_FIXEDFILEINFO(参见 Figure 6),此结构包含“固定的”版本信息,其中有主版本号和次版本号,还有一些 DLLVERSIONINFO 里的东西。使用 CModuleVersion 时,只要像下面这样写即可:CModuleVersion ver;if (ver.GetFileVersionInfo(_T(comctl32.dll) WORD major = HIWORD(ver.dwFileVersionMS); WORD minor = LOWORD(ver.dwFileVersionMS); .为了存取 CompanyName 这样的可变信息以及内涵的模块创建信息,你可以用另外一个函数 CModuleVersion: GetValue,例如,下面代码段执行之后,sCompanyName 的值将类似“XYZ”或“Acme Corporation”这样的公司名称:CString sCompanyName = ver.GetValue(_T(CompanyName); CModuleVersion 隐藏了获取信息所要做的所有邋遢细节相信我,都是些邋遢细节!如果你只是想使用 CModuleVersion,那么看到这里就可以打住了;如果你想要了解 CModuleVersion 的工作原理,那就继续往下看。假设 CModuleVersion:GetFileVersionInfo 能加载模块并获取 HINSTANCE,它调用 :GetFileVersionInfoSize 来获取版本信息的大小,然后分配一个缓冲并调用 GetFileVersionInfo 来填充该缓冲。原始缓冲(CModuleVersion:m_pVersionInfo)是一个数据块,它包含固定的信息和可变信息。VerQueryValue 将一个指针指向你感兴趣的特定信息的起始位置。例如,为了得到固定的信息(VS_FIXEDFILEINFO),你得这样写:LPVOID lpvi;UINT iLen;VerQueryValue(buf, _T(), &lpvi, &iLen);此处 buf 是从 GetFileVersionInfo 返回的完整信息。字符串“”(在 C 中用“”),你如果把它看作是一个目录,那它就是根信息(有一点像注册表)。VerQueryValue 将 lpvi 置到 VS_FIXEDFILEINFO 的起始处,iLen 为其长度。以上是获取固定信息的方法,可变信息获取更奇怪,因为你必须首先知道语言 ID 和代码页是什么。在 Winidows 里,代码页指定了一个字符集,它是字符文字与表示它们的 1 或 2 字节值之间映射。标准的 ANSI 代码页是 1252;Unicode 是 1200。Figure 7 是语言ID和代码页的清单。Figure 4 中文件信息里的 Translation 键指定模块的语言ID和代码页。在 CModuleVersion 中,我使用自己的 Translation 结构来获取这个信息。/ in CModuleVersionstruct TRANSLATION WORD langID / language IDWORD charset; / code page m_translation;为了获取语言信息,CModuleVersion 用 VerQueryValue 函数以 VarFileInfoTranslation 作为键。if (VerQueryValue(m_pVersionInfo,VarFileInfoTranslation, &lpvi, &iLen) & iLen = 4) m_translation = *(TRANSLATION*)lpvi;一旦你知道了语言ID和代码页,你就可以得到 CompanyName 和 InternalName 这样的可变信息。实现方法是构造一个如下形式的查询:StringFileInfolangIDcodepagekeyname这里 是十六进制 ASCI 形式的语言ID(中文是 0804;US English 是 0409),是代码页,格式为(1252 即 ANSI 的代码页是04e4),是你想要的键,如:CompanyName。为了构造这个查询,你得用 sprintf 或者 CString:Format 来构造字符串:StringFileInfo040904e4CompanyName然后将这个字符串传给 VerQueryValue。如果你对这些繁琐的细节感到晕菜,不用担心很幸运,CModuleVersion:GetValue 对所有邋遢细节都进行了封装,所以你只要像下面这样写即可:CString s = ver.GetValue(_T(CompanyName);实现了 CModuleVersion,VersionDlg 就简单多了。 它实际上就是一个对话框,这个对话框带有一个编辑框,用于输入模块名称,每当用户在编辑框中敲入模块名称时,MFC 便调用 ON_EN_CHANGE 消息处理例程 CVersionDialog:OnChangedModule。OnChangedModule 例程通过 CModuleVersion 对象及其 GetFileVersionInfo 和 GetDllVersion 函数来获得版本信息,然后将信息显示在对话框的两个静态文本控件中。这个过程很简单。最后还有个技巧我得提一下。GetFileVersionInfo,VerQueryValue 以及其它有关文件版本函数在一个叫做 version.lib 的库中,你必须将它链接到你程序中。从而避免链接时出现烦人的“undefined symbol”(未定义符号)错误,ModuleVer.h 使用了一个鲜为人知但特别有用的 #pragma comment 语法,即使你忘记在 Project|Settings 的 Link 属性页中添加 Input =Libraries 也没关系,#pragma comment 会告诉链接器与 version.lib 链接。/ 告诉链接器与 version.lib 进行链接#pragma comment(linker,/defaultlib:version.lib)现在,有人可能会问,为什么这些东西如此重要?以及谁会需要这些东西呢?一般来说,如果你编写的是显示文件属性之类的工具程序,那你只是需要获取诸如 CompanyName 和 LegalCopyright 之类的变量。但你也许发现用 CModuleVersion 从自己的应用程序中吸取文件信息很有用,例如,为了在“关于”对话框和启动屏幕中显示版本信息。如果你使用 CModuleVersion,你只需修改资源文件中相应位置的版本信息即可,“关于”对话框和启动屏幕会自动显示当前最新版本信息。版本信息另一个重要的用途是确定某个DLL是针对哪种语言编写的,这样你代码能与之对应。随着当今基于 Windows 的编程技术迅猛发展,DLLs 的新版本也随之日新月异,你很快就会发现下面这样的代码越来越多:if (version = 470)/ do one thingelse if (version=471)/ do something elseelse if (version=472)/ do a third thingelse/ scream这是一件很郁闷的事情,我敢说这也是微软的大佬们引入 DllGetVersion 来快速获取版本号的一个原因,从而避免了面对让人恐惧的 GetFileVersionInfo 函数,只用它来获取语言 IDs 和代码页(仅在需要获取诸如 Company
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025版广东土地估价师协会职业培训服务合同
- 2025版数字媒体广告资源包租赁合同模板
- 二零二五年度信息技术培训与咨询服务协议
- 二零二五版房产收购项目合作续约合同样本
- 二零二五年度商业地产项目场地转租及投资回报协议
- 二零二五版建筑信息模型(BIM)技术应用合同意向书
- 2025版环保材料消费贷款担保合同
- 2025版城市综合体房地产评估报告合同
- 二零二五版德汉翻译及国际文化交流项目合同
- 二零二五家政洗衣店市场拓展合作协议
- 2025年山东威海城投集团子公司招聘工作人员19人自考难、易点模拟试卷(共500题附带答案详解)
- 野外作业安全知识培训
- 全国卫生健康系统职业技能竞赛(传染病防治监督)参考试题库(含答案)
- 劳务合作协议书范本 二人
- 2025年烘干香菇项目可行性研究报告
- 宜宾2024年四川宜宾市社会福利院招聘编外聘用人员15人笔试历年典型考点(频考版试卷)附带答案详解
- 风电吊装劳务分包合同
- 2.石化厂15万吨常减压及30万吨催化装置拆除
- 2025重庆市建筑安全员《B证》考试题库及答案
- 2025年江苏省盐城公证处招聘公证人员5人历年高频重点提升(共500题)附带答案详解
- 检察院书记员笔试试题
评论
0/150
提交评论