2013年4月9日 星期二

VC++ GetFileVersion


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; 
GetFileVersionInfoSize 函數用於判斷系統能否檢索到指定文件的版本信息,如果可以,函數返回版本信息的字節大小:
DWORD  WINAPI GetFileVersionInfoSize( 

  __in        LPCTSTR  lptstrFilename,  //指定文件的名稱 

  __out_opt   LPDWORD  lpdwHandle  //一個變量的指針,該函數將該變量設為0 

); 
GetFileVersionInfo 函數用來獲得指定文件的版本信息:
BOOL  WINAPI GetFileVersionInfo( 

  __in         LPCTSTR  lptstrFilename,  //文件名 

  __reserved   DWORD  dwHandle,  //保留值 

  __in         DWORD  dwLen,  //lpData指向緩衝區的大小,使用函數GetFileVersionInfoSize得到 

  __out        LPVOID  lpData  //指向存放文件版本信息的緩衝區的指針 

); 
  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指向的數據的字節大小 

); 

上面參數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_ 
頭文件的實現如下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; 

} 

資料來源: http://blog.csdn.net/ace1985/article/details/5732024

沒有留言:

張貼留言