如果你只是想使用 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是什么意思等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)