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

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

如果你只是想使用 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,而是可以随你程序的更新包及其它文件一起分发。

最近苹果的热更新和私有库问题检查的更严了,如果应用被拒,苹果在拒绝信中会说到使用strings/otool/nm命令进行自查,所以总结了一些命令,方便查找和定位文件内容相关信息。

1、grep

作用:判断是否包含字符串

使用示例:

grep -r "xxx” path

检查是否包含(weixin)字符串:

img_57e6d38b0081c0cbef4d583a2c199f17png

grep -r "xxx” pathpng

matches 表示包含。

2、strings

作用:find the printable strings in a object, or other binary, file

使用示例:

strings aout | grep hello //检查 aout 文件中含有 hello 字符串的字节序列

检查二进制是否含有关键词的库(比如检查私有库):

img_2fde1511561581b197f01a3d24a32993png

strings aout | grep hellopng

更多使用说明 man strings

3、otool

作用: object file displaying tool (针对目标文件的展示工具,用来发现应用中使用到了哪些系统库,调用了其中哪些方法,使用了库中哪些对象及属性)

使用示例:

otool -L path //查看可执行程序都链接了那些库

otool -L path | grep "xxx" //筛选是否链接了xxx库

otool -D path //查看支持的架构

otool -ov path //output the Objective-C class structures and their defined methods(输出Object-C类结构以及定义的方法)

查看该应用是否砸壳:

otool -l path | grep crypt //cryptid 0(砸壳) 1(未砸壳)

img_efeec75834a8e30991e645c18486feb1png

otool -l path | grep cryptpng

更多用法 man otool

4、nm

作用:display name list (symbol table) (显示符号表)

使用示例:

nm path //得到Mach-O中的程序符号表

nm -nm path//目标文件的所有符号

img_215cf45e7d6046aa159b9fa2330eb133png

nm -nm pathpng

符号表中标示为 undefined,意思是目标文件引用了类_XXX(XXX库),不过这并没有实现它。

更多用法 man nm

5、file

作用:determine file type (判断文件类型)

使用示例:

file path

判断a/framework是静态库还是动态库:

静态库:

img_99db82e1092fe39753e415129b9c37f5png

file path - static Libpng

动态库:

img_765aa0e2f994d9653df690c1b9d6118fpng

file path - dynamically Libpng

6、lipo

作用:create or operate on universal files(创建或处理通用文件的工具)

使用示例:

lipo -info 'file path' // 判断静态库所支持的平台 - i386 armv7 armv7s x86_64 arm64

lipo -remove i386 origin_xxxa -output op_xxxa // 删除静态库包括的i386平台

lipo -thin i386 origin_xxxa -output op_xxxa // 拆分静态库,只保留i386 CPU架构

lipo -create device_xxxa simulator_xxxa -output universal_xxxa //对真机或者模拟器分别打出 a 文件合并

不是C语言吧?是系统命令。用来列举object文件(比如编译出的aout)的symbols

用法是:

nm [-a|--debug-syms] [-g|--extern-only]

[-B] [-C|--demangle[=style]] [-D|--dynamic]

[-S|--print-size] [-s|--print-armap]

[-A|-o|--print-file-name]

[-n|-v|--numeric-sort] [-p|--no-sort]

[-r|--reverse-sort] [--size-sort] [-u|--undefined-only]

[-t radix|--radix=radix] [-P|--portability]

[--target=bfdname] [-fformat|--format=format]

[--defined-only] [-l|--line-numbers] [--no-demangle]

[-V|--version] [-X 32_64] [--help] [objfile]

具体而言,nm用来列出目标文件的符号清单。

如果没有为nm命令指出目标文件,则nm假定目标文件是aout。下面列出该命令的任选项,大部分支持“-”开头的短格式和“-“开头的长格式。

-A、-o或--print-file-name:在找到的各个符号的名字前加上文件名,而不是在此文件的所有符号前只出现文件名一次。

例如nmlibtesta的输出如下:

CPThreado:

00000068TMain__8CPThreadPv

00000038TStart__8CPThread

00000014T__8CPThread

00000000T__8CPThread

00000000__FRAME_BEGIN__

…………………………………

则nm-A的输出如下:

libtesta:CPThreado:00000068TMain__8CPThreadPv

libtesta:CPThreado:00000038TStart__8CPThread

libtesta:CPThreado:00000014T__8CPThread

libtesta:CPThreado:00000000T__8CPThread

libtesta:CPThreado:00000000__FRAME_BEGIN__

…………………………………………………………

-a或--debug-syms:显示调试符号。

-B:等同于--format=bsd,用来兼容MIPS的nm。

-C或--demangle:将低级符号名解码(demangle)成用户级名字。这样可以使得C 函数名具有可读性。

-D或--dynamic:显示动态符号。该任选项仅对于动态目标(例如特定类型的共享库)有意义。

-fformat:使用format格式输出。format可以选取bsd、sysv或posix,该选项在GNU的nm中有用。默认为bsd。

-g或--extern-only:仅显示外部符号。

-n、-v或--numeric-sort:按符号对应地址的顺序排序,而非按符号名的字符顺序。

-p或--no-sort:按目标文件中遇到的符号顺序显示,不排序。

-P或--portability:使用POSIX2标准输出格式代替默认的输出格式。等同于使用任选项-fposix。

-s或--print-armap:当列出库中成员的符号时,包含索引。索引的内容包含:哪些模块包含哪些名字的映射。

-r或--reverse-sort:反转排序的顺序(例如,升序变为降序)。

--size-sort:按大小排列符号顺序。该大小是按照一个符号的值与它下一个符号的值进行计算的。

-tradix或--radix=radix:使用radix进制显示符号值。radix只能为“d”表示十进制、“o”表示八进制或“x”表示十六进制。

--target=bfdname:指定一个目标代码的格式,而非使用系统的默认格式。

-u或--undefined-only:仅显示没有定义的符号(那些外部符号)。

-l或--line-numbers:对每个符号,使用调试信息来试图找到文件名和行号。对于已定义的符号,查找符号地址的行号。对于未定义符号,查找指向符号重定位入口的行号。如果可以找到行号信息,显示在符号信息之后。

-V或--version:显示nm的版本号。

--help:显示nm的任选项。

ar cs libmya//创建一个库

ar rs libmya 1o//增加一个模块

ar t libmya//显示库里的模块

ar d libmya 1o//删除一个模块

以上就是关于如何获取某个动态链接库的版本信息全部的内容,包括:如何获取某个动态链接库的版本信息、mac 命令 显示文件夹内容、linux系统C语言的nm是什么意思等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/10157686.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-05
下一篇 2023-05-05

发表评论

登录后才能评论

评论列表(0条)

保存