
如何获取某个动态链接库的版本信息
展开全部
如果你只是想使用 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 = 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,而是可以随你程序的更新包及其它文件一起分发。
展开全部
ldd <可执行文件名> 查看可执行文件链接了哪些
系统动态链接库
nm <可执行文件名>
查看可执行文件里面有哪些符号
strip <可执行文件名>
去除符号表可以给可执行文件瘦身
如果我们想从可执行程序里面提取出来一点什么文本信息的话,还可以用strings命令
strings
<可执行文件名>
Linux操作系统上面的动态共享库大致分为三类:
1、操作系统级别的共享库和基础的系统工具库
比方说libc.so, libz.so,
libpthread.so等等,这些系统库会被放在/lib和/usr/lib目录下面,如果是64位操作系统,还会有/lib64和/usr
/lib64目录。如果操作系统带有图形界面,那么还会有/usr/X11R6/lib目录,如果是64位操作系统,还有/usr/X11R6
/lib64目录。此外还可能有其他特定Linux版本的系统库目录。
这些系统库文件的完整和版本的正确,确保了Linux上面各种程序能够正常的运行。
2、应用程序级别的系统共享库
并非操作系统自带,但是可能被很多应用程序所共享的库,一般会被放在/usr/local/lib和/usr/local/lib64这两个目录下面。很多你自行编译安装的程序都会在编译的时候自动把/usr/local/lib加入gcc的-L参数,而在运行的时候自动到/usr/local
/lib下面去寻找共享库。
以上两类的动态共享库,应用程序会自动寻找到他们,并不需要你额外的设置和担心。这是为什么呢?因为以上这些目录默认就被加入到动态链接程序的搜索路径里面了。Linux的系统共享库搜索路径定义在/etc/ld.so.conf这个配置文件里面。这个文件的内容格式大致如下:
/usr/X11R6/lib64
/usr/X11R6/lib
/usr/local/lib
/lib64
/lib
/usr/lib64
/usr/lib
/usr/local/lib64
/usr/local/ImageMagick/lib
假设我们自己编译安装的ImageMagick图形库在/usr/local/ImageMagick目录下面,并且希望其他应用程序都可以使用
ImageMagick的动态共享库,那么我们只需要把/usr/local/ImageMagick/lib目录加入/etc/ld.so.conf文件里面,然后执行:ldconfig
命令即可。
ldcofig将搜索以上所有的目录,为共享库建立一个缓存文件/etc/ld.so.cache。为了确认ldconfig已经搜索到ImageMagick的库,我们可以用上面介绍的strings命令从ld.so.cache里面抽取文本信息来检查一下:
strings
/etc/ld.so.cache | grep ImageMagick
输出结果为:
/usr/local/ImageMagick/lib/libWand.so.10
/usr/local/ImageMagick/lib/libWand.so
/usr/local/ImageMagick/lib/libMagick.so.10
/usr/local/ImageMagick/lib/libMagick.so
/usr/local/ImageMagick/lib/libMagick++.so.10
/usr/local/ImageMagick/lib/libMagick++.so
已经成功了!
3、应用程序独享的动态共享库
有很多共享库只被特定的应用程序使用,那么就没有必要加入系统库路径,以免应用程序的共享库之间发生版本冲突。因此Linux还可以通过设置环境变量LD_LIBRARY_PATH来临时指定应用程序的共享库搜索路径,就像我们上面举的那个例子一样,我们可以在应用程序的启动脚本里面预先设置
LD_LIBRARY_PATH,指定本应用程序附加的共享库搜索路径,从而让应用程序找到它。
系统动态链接库
nm <可执行文件名>
查看可执行文件里面有哪些符号
strip <可执行文件名>
去除符号表可以给可执行文件瘦身
如果我们想从可执行程序里面提取出来一点什么文本信息的话,还可以用strings命令
strings
<可执行文件名>
Linux操作系统上面的动态共享库大致分为三类:
1、操作系统级别的共享库和基础的系统工具库
比方说libc.so, libz.so,
libpthread.so等等,这些系统库会被放在/lib和/usr/lib目录下面,如果是64位操作系统,还会有/lib64和/usr
/lib64目录。如果操作系统带有图形界面,那么还会有/usr/X11R6/lib目录,如果是64位操作系统,还有/usr/X11R6
/lib64目录。此外还可能有其他特定Linux版本的系统库目录。
这些系统库文件的完整和版本的正确,确保了Linux上面各种程序能够正常的运行。
2、应用程序级别的系统共享库
并非操作系统自带,但是可能被很多应用程序所共享的库,一般会被放在/usr/local/lib和/usr/local/lib64这两个目录下面。很多你自行编译安装的程序都会在编译的时候自动把/usr/local/lib加入gcc的-L参数,而在运行的时候自动到/usr/local
/lib下面去寻找共享库。
以上两类的动态共享库,应用程序会自动寻找到他们,并不需要你额外的设置和担心。这是为什么呢?因为以上这些目录默认就被加入到动态链接程序的搜索路径里面了。Linux的系统共享库搜索路径定义在/etc/ld.so.conf这个配置文件里面。这个文件的内容格式大致如下:
/usr/X11R6/lib64
/usr/X11R6/lib
/usr/local/lib
/lib64
/lib
/usr/lib64
/usr/lib
/usr/local/lib64
/usr/local/ImageMagick/lib
假设我们自己编译安装的ImageMagick图形库在/usr/local/ImageMagick目录下面,并且希望其他应用程序都可以使用
ImageMagick的动态共享库,那么我们只需要把/usr/local/ImageMagick/lib目录加入/etc/ld.so.conf文件里面,然后执行:ldconfig
命令即可。
ldcofig将搜索以上所有的目录,为共享库建立一个缓存文件/etc/ld.so.cache。为了确认ldconfig已经搜索到ImageMagick的库,我们可以用上面介绍的strings命令从ld.so.cache里面抽取文本信息来检查一下:
strings
/etc/ld.so.cache | grep ImageMagick
输出结果为:
/usr/local/ImageMagick/lib/libWand.so.10
/usr/local/ImageMagick/lib/libWand.so
/usr/local/ImageMagick/lib/libMagick.so.10
/usr/local/ImageMagick/lib/libMagick.so
/usr/local/ImageMagick/lib/libMagick++.so.10
/usr/local/ImageMagick/lib/libMagick++.so
已经成功了!
3、应用程序独享的动态共享库
有很多共享库只被特定的应用程序使用,那么就没有必要加入系统库路径,以免应用程序的共享库之间发生版本冲突。因此Linux还可以通过设置环境变量LD_LIBRARY_PATH来临时指定应用程序的共享库搜索路径,就像我们上面举的那个例子一样,我们可以在应用程序的启动脚本里面预先设置
LD_LIBRARY_PATH,指定本应用程序附加的共享库搜索路径,从而让应用程序找到它。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询