WEB开发网
开发学院软件开发VC 如何获取某个动态链接库的版本信息 阅读

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

 2010-07-25 20:46:46 来源:WEB开发网   
核心提示:此处 buf 是从 GetFileVersionInfo 返回的完整信息,字符串“”(在 C 中用“\”),如何获取某个动态链接库的版本信息(3),你如果把它看作是一个目录,那它就是根信息(有一点像注册表),而是可以随你程序的更新包及其它文件一起分发,详情参见:http:

此处 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,"\VarFileInfo\Translation", &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\040904e4\CompanyName

然后将这个字符串传给 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 thing
else if (version==471)
// do something else
else if (version==472)
// do a third thing
else
// scream

这是一件很郁闷的事情,我敢说这也是微软的大佬们引入 DllGetVersion 来快速获取版本号的一个原因,从而避免了面对让人恐惧的 GetFileVersionInfo 函数,只用它来获取语言 IDs 和代码页(仅在需要获取诸如 CompanyName 这样的信息时使用)。

comctl32.dll 的与众不同也没有什么意外的,这个模块版本问题已经程序员最大的祸害之一,我可怜的邮箱曾被读者关于 comctl32.dll 这个模块的问题撑爆,很多问题都是客户下载了微软最新版本的 comctl32.dll 到机器上之后,应用程序就无法运行了。我会在以后的文章中解释 comctl32.dll 的版本问题,以及新的 toolbar 特性,如何解决 MFC 中 CToolBar 的 bug。现在,由于篇幅所限,我只能点到为止,目前 comctl32.dll 最新的版本为 6.00(随 IE 一起发布)。

最后,感谢上帝,微软已经出台关于可以随你的应用程序一起分发 comctl32.dll!但不是单独分发 comctl32.dll,而是可以随你程序的更新包及其它文件一起分发。详情参见:http://msdn.microsoft.com/developer/downloads/files/40comupd.htm,请在你的新版本出炉之前仔细阅读。

本文配套源码

上一页  1 2 3 

Tags:如何 获取 某个

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接