1. 程式人生 > >怎麼取檔案版本號 WindowsAPI之GetFileVersionInfo函式和VerQueryValue函式

怎麼取檔案版本號 WindowsAPI之GetFileVersionInfo函式和VerQueryValue函式

VS_FIXEDFILEINFO結構包含了檔案的版本資訊:

typedef struct tagVS_FIXEDFILEINFO { DWORD dwSignature; //包含的值是0xFEEF04BD DWORD dwStrucVersion; //該結構的32位二進位制版本號,高16位是主版本號,低16位是副版本號 DWORD dwFileVersionMS; //該檔案二進位制版本號的高32bits DWORD dwFileVersionLS; //該檔案二進位制版本號的低32bits DWORD dwProductVersionMS; //釋出該檔案的產品二進位制版本號高32bits DWORD dwProductVersionLS; //釋出該檔案的產品二進位制版本號低32bits DWORD dwFileFlagsMask; //位元掩碼,標誌dwFileFlags的有效位 DWORD dwFileFlags; //VS_FF_DEBUG—該檔案包含除錯資訊或是由除錯版編譯的 //VS_FF_INFOINFERRED—檔案的版本結構是動態建立的, //因此,該結構中有的成員是空的或不正確的 //VS_FF_PATCHED—該檔案被修改過 //VS_FF_PRERELEASE—該檔案是開發版,不是商業釋出版 //VS_FF_PRIVATEBUILD—該檔案不是由標準釋出步驟構建的 //VS_FF_SPECIALBUILD—該檔案是由標準釋出步驟構建的, //但是相同版本號檔案的變種 DWORD dwFileOS; //該檔案設計用於的作業系統 DWORD dwFileType; //檔案型別:VFT_APP—檔案包含一個應用程式 VFT_DLL—檔案包含一個DLL VFT_DRV—檔案包含一個裝置驅動 VFT_FONT—檔案包含一個字型檔案 VFT_STATIC_LIB—檔案包含一個靜態連結庫 VFT_UNKNOWN—檔案型別未知 VFT_VXD—檔案包含一個虛擬裝置 DWORD dwFileSubtype; //檔案的子型別,由dwFileType決定 DWORD dwFileDateMS; //二進位制檔案建立日期和時間戳的高32bits DWORD dwFileDateLS; //二進位制檔案建立日期和時間戳的低32bits } VS_FIXEDFILEINFO; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 GetFileVersionInfoSize函式用於判斷系統能否檢索到指定檔案的版本資訊,如果可以,函式返回版本資訊的位元組大小

DWORD WINAPI GetFileVersionInfoSize( __in LPCTSTR lptstrFilename, //指定檔案的名稱 __out_opt LPDWORD lpdwHandle //一個變數的指標,該函式將該變數設為0 ); 1 2 3 4 GetFileVersionInfo函式用來獲得指定檔案的版本資訊:

BOOL WINAPI GetFileVersionInfo( __in LPCTSTR lptstrFilename, //檔名 __reserved DWORD dwHandle, //保留值 __in DWORD dwLen, //lpData指向緩衝區的大小,使用函式GetFileVersionInfoSize得到 __out LPVOID lpData //指向存放檔案版本資訊的緩衝區的指標 ); 1 2 3 4 5 6 VerQueryValue函式用於從指定的版本資訊源獲取版本資訊,在呼叫該函式之前,需要先依次呼叫函式GetFileVersionInfoSize和GetFileVersionInfo:

BOOL WINAPI VerQueryValue( __in LPCVOID pBlock, //由函式GetFileVersionInfo得到的版本資訊源 __in LPCTSTR lpSubBlock, //“/”表示該函式獲取VS_FIXEDFILEINFO結構資訊 //為“/VarFileInfo/Translation”表示該函式獲取檔案的翻譯表 //為“/StringFileInfo/lang-codepage/string-name”表示該函式獲取檔案的字串資訊 __out LPVOID *lplpBuffer, //返回指向pBlock指向的地址,當pBlock被釋放時,該引數也被釋放 __out PUINT puLen //lplpBuffer指向的資料的位元組大小 ); 1 2 3 4 5 6 7 8 上面引數lpSubBlock取值中的string-name必須是下面系統預定義的字串之一: 這裡寫圖片描述 下面程式碼例項封裝了一個檔案版本資訊類,使用上面介紹的函式方便地獲取檔案版本資訊,標頭檔案定義如下FileVersion.h:

// FileVersion.h: interface for the CFileVersion class. // by Manuel Laflamme ////////////////////////////////////////////////////////////////////// #ifndef _FILEVERSION_H #define _FILEVERSION_H #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 class CFileVersion { // Construction public: CFileVersion(); // Operations public: BOOL Open(LPCTSTR lpszModuleName); void Close(); CString QueryValue(LPCTSTR lpszValueName, DWORD dwLangCharset = 0); CString GetFileDescription() {return QueryValue(_T(“FileDescription”)); }; CString GetFileVersion() {return QueryValue(_T(“FileVersion”)); }; CString GetInternalName() {return QueryValue(_T(“InternalName”)); }; CString GetCompanyName() {return QueryValue(_T(“CompanyName”)); }; CString GetLegalCopyright() {return QueryValue(_T(“LegalCopyright”)); }; CString GetOriginalFilename() {return QueryValue(_T(“OriginalFilename”));}; CString GetProductName() {return QueryValue(_T(“ProductName”)); }; CString GetProductVersion() {return QueryValue(_T(“ProductVersion”)); }; BOOL GetFixedInfo(VS_FIXEDFILEINFO& vsffi); CString GetFixedFileVersion(); CString GetFixedProductVersion(); // Attributes protected: LPBYTE m_lpVersionData; DWORD m_dwLangCharset; // Implementation public: ~CFileVersion(); }; #endif // _FILEVERSION_H 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 標頭檔案的實現如下FileVersion.cpp:

// FileVersion.cpp: implementation of the CFileVersion class. // by Manuel Laflamme ////////////////////////////////////////////////////////////////////// #include “FileVersion.h” #pragma comment(lib, “version”) #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=FILE; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// CFileVersion::CFileVersion() { m_lpVersionData = NULL; m_dwLangCharset = 0; } CFileVersion::~CFileVersion() { Close(); } void CFileVersion::Close() { delete[] m_lpVersionData; m_lpVersionData = NULL; m_dwLangCharset = 0; } BOOL CFileVersion::Open(LPCTSTR lpszModuleName) { ASSERT(_tcslen(lpszModuleName) > 0); ASSERT(m_lpVersionData == NULL); // Get the version information size for allocate the buffer DWORD dwHandle; DWORD dwDataSize = ::GetFileVersionInfoSize((LPTSTR)lpszModuleName, &dwHandle); if ( dwDataSize == 0 ) return FALSE; // Allocate buffer and retrieve version information m_lpVersionData = new BYTE[dwDataSize]; if (!::GetFileVersionInfo((LPTSTR)lpszModuleName, dwHandle, dwDataSize, (void**)m_lpVersionData) ) { Close(); return FALSE; } // Retrieve the first language and character-set identifier UINT nQuerySize; DWORD* pTransTable; if (!::VerQueryValue(m_lpVersionData, _T("//VarFileInfo//Translation"), (void )&pTransTable, &nQuerySize) ) { Close(); return FALSE; } // Swap the words to have lang-charset in the correct format m_dwLangCharset = MAKELONG(HIWORD(pTransTable[0]), LOWORD(pTransTable[0])); return TRUE; } CString CFileVersion::QueryValue(LPCTSTR lpszValueName, DWORD dwLangCharset / = 0/) { // Must call Open() first ASSERT(m_lpVersionData != NULL); if ( m_lpVersionData == NULL ) return (CString)_T(""); // If no lang-charset specified use default if ( dwLangCharset == 0 ) dwLangCharset = m_dwLangCharset; // Query version information value UINT nQuerySize; LPVOID lpData; CString strValue, strBlockName; strBlockName.Format(_T("\StringFileInfo\%08lx\%s"), dwLangCharset, lpszValueName); if ( ::VerQueryValue((void *)m_lpVersionData, strBlockName.GetBuffer(0), &lpData, &nQuerySize) ) strValue = (LPCTSTR)lpData; strBlockName.ReleaseBuffer(); return strValue; } BOOL CFileVersion::GetFixedInfo(VS_FIXEDFILEINFO& vsffi) { // Must call Open() first ASSERT(m_lpVersionData != NULL); if ( m_lpVersionData == NULL ) return FALSE; UINT nQuerySize; VS_FIXEDFILEINFO pVsffi; if ( ::VerQueryValue((void )m_lpVersionData, _T("\"), (void)&pVsffi, &nQuerySize) ) { vsffi = *pVsffi; return TRUE; } return FALSE; } CString CFileVersion::GetFixedFileVersion() { CString strVersion; VS_FIXEDFILEINFO vsffi; if ( GetFixedInfo(vsffi) ) { strVersion.Format (_T("%u,%u,%u,%u"),HIWORD(vsffi.dwFileVersionMS), LOWORD(vsffi.dwFileVersionMS), HIWORD(vsffi.dwFileVersionLS), LOWORD(vsffi.dwFileVersionLS)); } return strVersion; } CString CFileVersion::GetFixedProductVersion() { CString strVersion; VS_FIXEDFILEINFO vsffi; if ( GetFixedInfo(vsffi) ) { strVersion.Format (_T("%u,%u,%u,%u"), HIWORD(vsffi.dwProductVersionMS), LOWORD(vsffi.dwProductVersionMS), HIWORD(vsffi.dwProductVersionLS), LOWORD(vsffi.dwProductVersionLS)); } return strVersion; }