用vc如何获取某个动态链接库的版本信息

用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 cbSizeDWORD dwMajorVersionDWORD dwMinorVersionDWORD dwBuildNumberDWORD dwPlatformID DLLVERSIONINFO 这个结构中的字段基本不用怎么说明就知道是什么意思dwPlatformID msinfo
为DLLVER_PLATFORM_WINDOWS value 1指Windows 9x而DLLVER_PLATFORM_NT value 2用于Windows NT。一旦定义了DLLVERSIONINFO 结构就可以调用DllGetVersion 了该函数的署名如下HRESULT DllGetVersionDLLVERSIONINFO 因为并不是任何给定的Dll 都输出DllGetVersion 函数你得按照标准套路来调用它即调用GetProcAddress 并判断返回值是否为NULL。我编写的类CModuleVersion 中? 幸桓?DllGetVersion 函数它把所有细节都进行了封装参见Figure 2 中的ModulVer.cpp。CModuleVersion 类的使用方法如下DLLVERSIONINFO dviif CModuleVersion::DllGetVersioncomctl32.dll dvi // now info is in dvi DllGetVersion 是一个比较新的函数译者注在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 verif ver.GetFileVersionInfo_Tcomctl32.dll WORD major HIWORDver.dwFileVersionMS WORD minor
LOWORDver.dwFileVersionMS ... 为了存取CompanyName 这样的可变信息以及
内涵的模块创建信息你可以用另外一个函数CModuleVersion:: GetValue例如下面
代码段执行之后sCompanyName 的值将类似“XYZ”或“Acme Corporation”这样的公司名称CString sCompanyName ver.GetValue_TCompanyName CModuleVersion 隐藏了获取信息所要做的所有邋遢细节——相信我都是些邋遢细节如果你只是想使用CModuleVersion那么看到这里就可以打住了如果你想要了解CModuleVersion 的工作原理那就继续往下看。假设CModuleVersion::GetFileVersionInfo 能加载模块并获取HINSTANCE它调用::GetFileVersionInfoSize 来获取版本信息的大小然后分
配一个缓冲并调用GetFileVersionInfo 来填充该缓冲。原始缓冲CModuleVersion::m_pVersionInfo是一个数据块它包含固定的信息和可变信息。VerQueryValue 将一个指针指向你感兴趣的特定信息的起始位置。例如为了得到固定的信息VS_FIXEDFILEINFO你得这样写LPVOID lpviUINT iLenVerQueryValuebuf _T lpvi iLen 此处buf 是从GetFileVersionInfo 返回的完整信息。字符串“”在  C 中用“”你如果把它看作是一个目录那它就是根信息有一点像注册表。VerQueryValue 将lpvi 置到VS_FI
XEDFILEINFO 的起始处iLen 为其长度。以上是获取固定信息的方法可变信息获取更奇怪因为你必须首先知道语言ID 和
代码页是什么。在Winidows 里代码页指定了一个字符集它是字符文字与表示它们的  1 或  2 字节值之间映射。标准的ANSI 代码页是1252Unicode 是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
VerQueryValuem_pVersionInfoVarFileInfoTranslation lpvi iLen iLen    4
m_translation TRANSLATIONlpvi 一旦你知道了语言ID和代码页你就可以得到CompanyName 和InternalName 这样的可变信息。实现方法是构造一个如下形式的查询StringFileInfolangIDcodepagekeyname 这里是十六进制ASCI 形式的语言ID 中文是0804US English 是0409是代码页格式为1252 即ANSI 的代码页是04e4是你想要的键如CompanyName。为了构造这个查询你得用sprintf 或者
CString::Format 来构造字符串StringFileInfo040904e4CompanyName 然后将这个字符串传给VerQuer
yValue。如果你对这些繁琐的细节感到晕菜不用担心——很幸运CModuleVersion::GetValue 对所有邋遢细节都进行了封装所以你只要像下面这样写即可CString s ver.GetValue_TCompanyName 实现了CModuleVersionVersionDlg 就简单多了。它实际上就是一个对话框这个对话框带有一个编辑框用于输入模块名称每当用户在编辑框中敲入模块名称时MFC 便调用ON_EN_CHANGE 消息处理例程CVersionDialog::OnChangedModule。OnChangedModule 例程通过CModuleVersion 对象及其GetFileVersionInfo 和GetDllVersion 函数来获得版本
信息然后将信息显示在对话框的两个静态文本控件中。这个过程很简单。最后还有
个技巧我得提一下。GetFileVersionInfoVerQueryValue 以及其它有关文件版本函数在一个叫做version.lib 的库中你必须将它链接到你程序中。从而避免链接时出现烦人的“undefined symbol”未定义符号错误ModuleVer.h 使用了一个鲜为人知但特别有用的pragma comment 语法即使你忘记在ProjectSettings 的Link 属性页中添加Input 〉Libraries 也没关系pragma comment 会告诉链接器与version.lib 链接。// 告诉链接器与version.lib 进行链接pragma commentlinker/defaultlib:version.lib 现在有人可能会问为什么这些东西如此重要以及谁会需要这些东西呢一般来说如果你编写的是显示文件属性之类的工具程序那你只是需要获取诸如CompanyName 和LegalCopyright 之类的变量。但你也许发现用CModuleVersion 从自己的应用程序中吸取文件信息很有用例如为了在“关于”对话框和启动屏幕中显示版本信息。如果你使用CModuleVersion你只需修改资源文件中相应位置的版本信息即可“关于”
对话框和启动屏幕会自动显示当前最新版本信息。版本信息另一个重要的用途是确定某个DLL是针对哪种语言编写的这样你代码能与之对应。随着当今基于Windows 的编程技术迅猛发展DLLs 的新版本也随之日新月异你很快就会发现下面这样的代码越来越多if version 470// do one thingelse if version471// do something elseelse if version472// do a third thingelse// scream 这是一件很郁闷的事情我敢说这也是微软
的大佬们引入DllGetVersion 来快速获取版本号的一个原因从而避免了面对让人恐惧的GetFileVersionInfo 函数只用它来获取语言IDs 和代码页仅在需要获取诸如CompanyName 这样的信息时使用。comctl32.dll 的与众不同也没有什么意外的这个模块版本问题已经程序员最大的祸害之一我可怜的邮箱曾被读者关于
comctl32.dll 这个模块的问题撑爆很多问题都是客户下载了微软最新版本的
comctl32.dll 到机器上之后应用程序就无法运行了。我会在以后的文章中解释comctl32.dll 的版本问题以及新的toolbar 特性如何解决MFC 中CToolBar 的bug。现在由于篇幅所限我只能点到为止目前comctl32.dll 最新的版本为6.00随IE 一起发布。

本文发布于:2024-09-22 01:03:08,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/4/380005.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:信息   版本   函数   方法   文件
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议