
如果你只是想使用 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 CModuleVersion struct TRANSLATION { WORD langID // language ID WORD charset; // code page } m_translation; 为了获取语言信息,CModuleVersion 用 VerQueryValue 函数以 VarFileInfoTranslation 作为键。if (VerQueryValue(m_pVersionInfo,"VarFileInfoTranslation", &lpvi, &iLen) && iLen >= 4) { m_translation = (TRANSLATION)lpvi; } 一旦你知道了语言ID和代码页,你就可以得到 CompanyName 和 InternalName 这样的可变信息。实现方法是构造一个如下形式的查询:StringFileInfo<langID><codepage><keyname> 这里<langID> 是十六进制 ASCI 形式的语言ID(中文是 0804;US English 是 0409),<codepage> 是代码页,格式为(1252 即 ANSI 的代码页是04e4),<keyname> 是你想要的键,如:CompanyName。为了构造这个查询,你得用 sprintf 或者 CString::Format 来构造字符串:StringFileInfo 40904e4CompanyName 然后将这个字符串传给 VerQueryValue。如果你对这些繁琐的细节感到晕菜,不用担心——很幸运,CModuleVersion::GetValue 对所有邋遢细节都进行了封装,所以你只要像下面这样写即可:CString s = verGetValue(_T("CompanyName")); 实现了 CModuleVersion,VersionDlg 就简单多了。 它实际上就是一个对话框,这个对话框带有一个编辑框,用于输入模块名称,每当用户在编辑框中敲入模块名称时,MFC 便调用 ON_EN_CHANGE 消息处理例程 CVersionDialog::OnChangedModule。OnChangedModule 例程通过 CModuleVersion 对象及其 GetFileVersionInfo 和 GetDllVersion 函数来获得版本信息,然后将信息显示在对话框的两个静态文本控件中。这个过程很简单。 最后还有个技巧我得提一下。GetFileVersionInfo,VerQueryValue 以及其它有关文件版本函数在一个叫做 versionlib 的库中,你必须将它链接到你程序中。从而避免链接时出现烦人的“undefined symbol”(未定义符号)错误,ModuleVerh 使用了一个鲜为人知但特别有用的 #pragma comment 语法,即使你忘记在 Project|Settings 的 Link 属性页中添加 Input ==〉Libraries 也没关系,#pragma comment 会告诉链接器与 versionlib 链接。// 告诉链接器与 versionlib 进行链接 #pragma comment(linker, "/defaultlib:versionlib") 现在,有人可能会问,为什么这些东西如此重要?以及谁会需要这些东西呢?一般来说,如果你编写的是显示文件属性之类的工具程序,那你只是需要获取诸如 CompanyName 和 LegalCopyright 之类的变量。但你也许发现用 CModuleVersion 从自己的应用程序中吸取文件信息很有用,例如,为了在“关于”对话框和启动屏幕中显示版本信息。如果你使用 CModuleVersion,你只需修改资源文件中相应位置的版本信息即可,“关于”对话框和启动屏幕会自动显示当前最新版本信息。 版本信息另一个重要的用途是确定某个DLL是针对哪种语言编写的,这样你代码能与之对应。随着当今基于 Windows 的编程技术迅猛发展,DLLs 的新版本也随之日新月异,你很快就会发现下面这样的代码越来越多:if (version <= 470) // do one thing else if (version==471) // do something else else if (version==472) // do a third thing else // scream 这是一件很郁闷的事情,我敢说这也是微软的大佬们引入 DllGetVersion 来快速获取版本号的一个原因,从而避免了面对让人恐惧的 GetFileVersionInfo 函数,只用它来获取语言 IDs 和代码页(仅在需要获取诸如 CompanyName 这样的信息时使用)。 comctl32dll 的与众不同也没有什么意外的,这个模块版本问题已经程序员最大的祸害之一,我可怜的邮箱曾被读者关于 comctl32dll 这个模块的问题撑爆,很多问题都是客户下载了微软最新版本的 comctl32dll 到机器上之后,应用程序就无法运行了。我会在以后的文章中解释 comctl32dll 的版本问题,以及新的 toolbar 特性,如何解决 MFC 中 CToolBar 的 bug。现在,由于篇幅所限,我只能点到为止,目前 comctl32dll 最新的版本为 600(随 IE 一起发布)。 最后,感谢上帝,微软已经出台关于可以随你的应用程序一起分发 comctl32dll!但不是单独分发 comctl32dll,而是可以随你程序的更新包及其它文件一起分发。
系统对应的软件版本号一定要正确,我一开始也出现了"无法正常启动"这样的错误,我查看了下ensp文件夹里也有virtualbox文件夹,我的virtualbox是60,教程上推荐的是50-52,然后我卸载了virtualbox60安装了virtualbox526,启动成功了
以上就是关于如何获取某个动态链接库的版本信息全部的内容,包括:如何获取某个动态链接库的版本信息、思科与华为ensp对应的软件是啥、等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)