取文件屬性

取文件屬性:GetFileVersionInfoSize,GetFileVersionInfo,VerQueryValue三個函數的配合
 

右鍵點擊一個文件,看它的屬性,會發現有很多東西。查了一下,有一個結構體可以用來獲得文件的屬性,不過得到的東西很有限,隱約記得是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了一下。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章