【转】取文件属性:GetFileVersionInfoSize,GetFileVersionInfo,VerQueryValue三个函数的配合

来源:互联网 发布:网络塔防游戏手机版 编辑:程序博客网 时间:2024/05/29 14:29

右键点击一个文件,看它的属性,会发现有很多东西。查了一下,有一个结构体可以用来获得文件的属性,不过得到的东西很有限,隐约记得是7个,比如文件名称,创建时间什么的。而查看不同的文件属性页里的内容是不一样的,比如以下一个exe文件



    这里面的产品说明之类的东西在有些文件里是没有的。当然,我还没研究太深,用一个可能不恰当的名词吧。只是觉得这些应该不属于“基本属性”,而本文开篇所提到的那些属性属于基本属性。像文件名称,各种时间之类的,应该所有文件都会有。

    再看这些属性们,会觉得很眼熟,打开一个VC++工程,可以在workspace里面看到这个

    打开这个文件,就能看到具体条目。

    对了,就是它,属性页里那些乱七八糟的“键值对”们就是在这里来的。下面就要得到它们。使用GetFileVersionInfoSize,GetFileVersionInfo,VerQueryValue三个函数配合使用。前两个好说,不过第三个VerQueryValue弄了好久也弄不明白。网上搜到了一个ID为EnochShen的网友(CSDN)的回帖,如下。先做一下搬运工。感谢EnochShen。在他的代码上面加一些我自己的说明文字吧。不作说明的注释都是我加上去的。不过,除了我注出来的一个地方用TCHAR不行之外,其他地方我全是用的TCHAR。

char* szFileName = "C:\\EnochShen.exe "; //文件的全路径,更实用的是动态获取
DWORD dwSize = GetFileVersionInfoSize(szFileName,NULL); //可查MSDN,函数用法。MSDN上说最后一个参数是需要置0的,我就弄了一个置0的变量DWORD dwVerSetZero = 0;把地址加进来,可看这个用法直接塞个NULL,试了下,也行。搞不明白有什么区别。
LPVOID pBlock = malloc(dwSize); //我没这样做,而是TCHAR* szVersionInfo = new TCHAR[4096];也没有问题,当然pBlock就改成了szVersionInfo这个名字
GetFileVersionInfo(szFileName,0,dwSize,pBlock);

char* pVerValue = NULL; //这里不能用TCHAR*,在后面代码VerQueryValue(szVersionInfo, strSubBlock, (LPVOID*)&pVerValue, &nBytes);中会出问题,应该是编译后搞成UNICODE的双字节了。

UINT nSize = 0; 
VerQueryValue(pBlock,TEXT( "\\VarFileInfo\\Translation "), 
(LPVOID*)&pVerValue,&nSize); //这是得到语言什么的,死板地套用就行了,我也还不明白

CString strSubBlock,strTranslation,strTemp; 
strTemp.Format( "000%x ",*((unsigned short int *)pVerValue)); 
strTranslation = strTemp.Right(4); 
strTemp.Format( "000%x ",*((unsigned short int *)&pVerValue[2])); 
strTranslation += strTemp.Right(4); 
//【原】080404b0为中文,040904E4为英文 //此注释不理解,其实我调试时,不是这两个数值,也还堪用。难道是火星文?

//【原】文件描述 
strSubBlock.Format( "\\StringFileInfo\\%s\\FileDescription ",strTranslation);

//上面这个字符串很重要,要读什么东西出来就是靠它了。后来想想,我只所以不会用,就是这个串不会用,总也不知道要取的属性在这里叫什么名字。当然,我用的形式如下

//strSubBlock.Format( _T("\\StringFileInfo\\%s\\ProductName"),strTranslation);嘛TCHAR

//不过我只用到了ProductName这一项,其他的都按原样列在下面。备忘吧。
VerQueryValue(pBlock,strSubBlock.GetBufferSetLength(256),(LPVOID*)&pVerValue,&nSize); 
strSubBlock.ReleaseBuffer(); 
strTemp.Format( "文件描述: %s ",pVerValue); 
AfxMessageBox(strTemp); //这个函数得改。我与EnochShen的上下文环境俨然不一样。我这里用不了。

//【原】内部名称 
strSubBlock.Format( "\\StringFileInfo\\%s\\InternalName ",strTranslation); 
VerQueryValue(pBlock,strSubBlock.GetBufferSetLength(256),(LPVOID*)&pVerValue,&nSize); 
strSubBlock.ReleaseBuffer(); 
strTemp.Format( "文件描述: %s ",pVerValue); 
AfxMessageBox(strTemp); 

//【原】合法版权 
strSubBlock.Format( "\\StringFileInfo\\%s\\LegalTradeMarks ",strTranslation); 
VerQueryValue(pBlock,strSubBlock.GetBufferSetLength(256),(LPVOID*)&pVerValue,&nSize); 
strSubBlock.ReleaseBuffer(); 
strTemp.Format( "合法版权: %s ",pVerValue); 
AfxMessageBox(strTemp); 

//【原】原始文件名 
strSubBlock.Format( "\\StringFileInfo\\%s\\OriginalFileName ",strTranslation); 
VerQueryValue(pBlock,strSubBlock.GetBufferSetLength(256),(LPVOID*)&pVerValue,&nSize); 
strSubBlock.ReleaseBuffer(); 
strTemp.Format( "原始文件名: %s ",pVerValue); 
AfxMessageBox(strTemp); 

//【原】产品名称 
strSubBlock.Format( "\\StringFileInfo\\%s\\ProductName ",strTranslation); 
VerQueryValue(pBlock,strSubBlock.GetBufferSetLength(256),(LPVOID*)&pVerValue,&nSize); 
strSubBlock.ReleaseBuffer(); 
strTemp.Format( "产品名称: %s ",pVerValue); 
AfxMessageBox(strTemp); 

//【原】产品版本 
strSubBlock.Format( "\\StringFileInfo\\%s\\ProductVersion ",strTranslation); 
VerQueryValue(pBlock,strSubBlock.GetBufferSetLength(256),(LPVOID*)&pVerValue,&nSize); 
strSubBlock.ReleaseBuffer(); 
strTemp.Format( "产品版本: %s ",pVerValue); 
AfxMessageBox(strTemp); 

free(pBlock); //我的是new出来的TCHAR,也free了一下。