Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

CFileVersionInfo - Getting the File Version Information

0.00/5 (No votes)
29 Mar 2004 1  
Class for getting file version information
This class wraps the GetFileVersionInfo, GetFileVersionInfoSize, VerQueryValue, and VerLanguageName API functions and can be used to determine full file version information.

Introduction

You can use this class to determine a full file version information, in any file that has version information resource, such as dynamic-link libraries (DLLs), executable files, font files, OCX files, etc., including version information blocks in multiple languages. This class wraps the GetFileVersionInfo, GetFileVersionInfoSize, VerQueryValue, and VerLanguageName API functions. See sample image below:

Image 1

Background

Once developing a DLL file, I wanted to implement DllGetVersion function in it (it returns the version of the DLL, if requested, see Platform SDK). Of course, I could return fixed version numbers from my implementation of it, but in that case, they would become wrong even after a single rebuild (I used version auto increment in that project). So I decided to use the API version information functions - i.e., read version information from the file version information resource and return it every time it was requested - and implemented CFileVersionInfo class.

Sample Usage

In this sample, we query the Shell32.dll version information (we'll get something in this format: "6.0.2600.0") and its company name string (we'll get something like "Microsoft Corporation"):

//...
#ifndef __VERINFO_H__
    #include < verinfo.h >
#endif
//...

CFileVersionInfo fvi;
if( fvi.Open( _T( "shell32.dll" ) )
{
    TCHAR szVer[ 512 ] = { 0 };
    ::wsprintf( szVer, 
        _T( "%d.%d.%d.%d" ),
        fvi.GetFileVersionMajor(),  // Major version
        fvi.GetFileVersionMinor(),  // Minor version
        fvi.GetFileVersionBuild(),  // Build number
        fvi.GetFileVersionQFE()     // QFE
    );

    /*
    VS_FIXEDFILEINFO vsffi = m_fvi.GetVSFFI();
    ::wsprintf( szVer, 
        _T( "%d.%d.%d.%d" ),
        HIWORD( vsffi.dwFileVersionMS ),  // Major version
        LOWORD( vsffi.dwFileVersionMS ),  // Minor version
        HIWORD( vsffi.dwFileVersionLS ),  // Build number
        LOWORD( vsffi.dwFileVersionLS )   // QFE
    );
    */
    
    ::SetWindowText( hWndVersion, szVer );

    if( fvi.QueryStringValue( VI_STR_COMPANYNAME, szVer, 512 ) )
        ::SetWindowText( hWndCompName, szVer );

//...

    fvi.Close();
}
//...

Translation Support

If application or DLL supports a list of languages (multi-language version info blocks), instead of using multiple version resources (for each language), you can use this class to get data from them separately, depending on the language identifier and code page:

Image 2

In the sample application, three different language and code page string table version blocks are provided, you can test them all. See the image before selection (above) and after it (below):

Image 3

Class Members

Base Class

  • Does not have a base class

Construction

  • CFileVersionInfo( void ) - Constructs a CFileVersionInfo object

Operations

  • BOOL Open( IN LPCTSTR lpszFileName ) - Opens the file version information by its name specified in lpszFileName
  • BOOL Open( IN HMODULE hModule )- Opens the file version information by its handle specified in hModule
  • void Close( void ) - Closes the specified module and frees the resources, loaded by Open method(s)
  • BOOL IsValid( void ) - Queries, whether the class internal data is valid

Version Information Retrieval

  • BOOL QueryStringValue( IN LPCTSTR lpszString, OUT LPTSTR lpszValue, IN INT nBuf ) const - Retrieves a value in a StringTable structure, and returns it in the nBuf size lpszValue buffer. The lpszString name must be one of the predefined strings, enumerated in the next function description. For example: m_ver.QueryStringValue( _T( "Comments" ), szBuf, 512 );.
    NOTE: It is better you use the second version of this function, explained below.
  • BOOL QueryStringValue( IN INT nIndex, OUT LPTSTR lpszValue, IN INT nBuf ) const - Retrieves a value in a StringTable structure, and returns it in the nBuf size lpszValue buffer. The nIndex name must be one of the following predefined constants:
    • VI_STR_COMMENTS - Comments
    • VI_STR_COMPANYNAME - CompanyName
    • VI_STR_FILEDESCRIPTION - FileDescription
    • VI_STR_FILEVERSION - FileVersion
    • VI_STR_INTERNALNAME - InternalName
    • VI_STR_LEGALCOPYRIGHT - LegalCopyright
    • VI_STR_LEGALTRADEMARKS - LegalTrademarks
    • VI_STR_ORIGINALFILENAME - OriginalFilename
    • VI_STR_PRIVATEBUILD - PrivateBuild
    • VI_STR_PRODUCTNAME - ProductName
    • VI_STR_PRODUCTVERSION - ProductVersion
    • VI_STR_SPECIALBUILD - SpecialBuild
    • VI_STR_OLESELFREGISTER - OLESelfRegister

    For example: m_ver.QueryStringValue( VI_STR_SPECIALBUILD, szBuf, 512 );

  • const VS_FIXEDFILEINFO& GetVSFFI( void ) const - Retrieves the reference to the VS_FIXEDFILEINFO structure of the open file version information.
  • LPCTSTR GetVerStringName( IN INT nIndex ) - Returns the version string name for the nIndex parameter from the array - the class holds a static array of version information strings, each value of which can be accessed by index. For example: m_ver.GetVerStringName( VI_STR_PRODUCTNAME )will return a pointer to _T( "ProductName" ) string.
  • GetVersionMajor( void ) const - get major version
  • GetVersionMinor( void ) const - get minor version
  • GetVersionBuild( void ) const - get build version
  • GetVersionQFE( void ) const - get QFE version

Static Members

  • BOOL GetLIDName( IN WORD wLID, OUT LPTSTR lpszName, IN INT nBuf ) - Retrieves a description string for the wLID language identifier and returns it in the lpszName buffer of nBuf size.
  • BOOL GetCPName( IN WORD wCP, OUT LPCTSTR* ppszName ) - Retrieves a description string for the wCP code page identifier and returns it in the lpszName buffer of nBuf size.

Translation Methods

  • BOOL SetTrans ( IN LANGID wLID /*= LANG_NEUTRAL*/, IN WORD wCP /*= VI_CP_UNICODE*/ ) - Sets the Language Identifier and Code Page to use in the version information data (if any)
  • INT FindTrans( IN LANGID wLID, IN WORD wCP ) const - Finds the translation (the Language Identifier and Code Page) in the version information data, if any
  • BOOL SetTransIndex( IN UINT nIndex /*= 0*/ ) - Sets the translation to use in the version information data by index (if any)
  • DWORD GetTransByIndex( IN UINT nIndex ) const - Extracts the translation (the Language Identifier and Code Page) at the specified index in the translation array (if any)

Inline Translation Methods

  • UINT GetTransCount( void ) const - Returns the number of translations, i.e., number of concatenations of a language and code page identifies pairs found in the translation array for the resource.
  • UINT GetCurTransIndex( void ) const - Returns the current index of the translation index in the translation array of the version resource.
  • LANGID GetLIDByIndex( IN UINT nIndex ) const - Extracts the Language Identifier from the langid-codepage translation pair at the specified index in the array (if any).
  • WORD GetCPByIndex( IN UINT nIndex ) const - Extracts the Code Page identifier from the langid-codepage translation pair at the specified index in the array (if any).
  • DWORD GetCurTrans( void ) const - Returns the langid-codepage translation pair currently set as default in the class.
  • LANGID GetCurLID( void ) const - Returns the Language Identifier currently set as default in the class.
  • WORD GetCurCP( void ) const - Returns the Code Page currently set as default in the class.

Global Functions

  • STDAPI_( HRESULT ) DllGetVersion( IN HMODULE hModule, OUT DLLVERSIONINFO* lpDVI ) - You can use this function in the exported DllGetVersion of any of your DLLs to do the black work - return the pointer to DLLVERSIONINFO structure filled with your app version data. It uses the CFileVersionInfo class. See its implementation:
    //...
    #ifndef __VERINFO_H__
        #include < verinfo.h >
    #endif
    //...
    
    HRESULT STDAPICALLTYPE DllGetVersion( IN  HMODULE hModule, 
                                          OUT DLLVERSIONINFO* lpDVI )
    {
        if( hModule == NULL || 
            ::IsBadReadPtr( lpDVI, sizeof( DLLVERSIONINFO* ) ) )
        {
            ASSERT_RETURN( S_FALSE );
        }
        
        const DWORD cbSize = lpDVI->cbSize;
        
        if(
    #ifdef DLLVERSIONINFO2
            (
    #endif
            cbSize != sizeof( DLLVERSIONINFO  )
    #ifdef DLLVERSIONINFO2
            && cbSize != sizeof( DLLVERSIONINFO2 ) ) 
    #endif
            || ::IsBadWritePtr( lpDVI, cbSize ) )
        {
            ASSERT_RETURN( S_FALSE );
        }
        
        ::ZeroMemory( lpDVI, cbSize );
        lpDVI->cbSize = cbSize;
        
        CFileVersionInfo fvi;
        if( fvi.Open( hModule ) )
        {
            VS_FIXEDFILEINFO vsffi = fvi.GetVSFFI();
        
            if( vsffi.dwFileType == VFT_DLL ||
                vsffi.dwFileType == VFT_STATIC_LIB )
            {
                switch( vsffi.dwFileOS )
                {            
                case VOS__WINDOWS32:
                case VOS_NT_WINDOWS32:
                    lpDVI->dwPlatformID = DLLVER_PLATFORM_WINDOWS;
                    break;
                case VOS_NT:
                    lpDVI->dwPlatformID = DLLVER_PLATFORM_NT;
                    break;            
                default:
                    return ( S_FALSE );
                }
        
                lpDVI->dwMajorVersion = HIWORD( vsffi.dwFileVersionMS );
                lpDVI->dwMinorVersion = LOWORD( vsffi.dwFileVersionMS );
                lpDVI->dwBuildNumber  = HIWORD( vsffi.dwFileVersionLS );
        
            #ifdef DLLVERSIONINFO2
    
                if( cbSize == sizeof( DLLVERSIONINFO2 ) )
                {
                    DLLVERSIONINFO2* lpDVI2 = (DLLVERSIONINFO2*)lpDVI;
                    lpDVI2->ullVersion = MAKEDLLVERULL( 
                        lpDVI->dwMajorVersion,
                        lpDVI->dwMinorVersion,
                        lpDVI->dwBuildNumber ,
                        LOWORD( vsffi.dwFileVersionLS )
                    );
                }
        
            #endif
        
                return ( S_OK );
            }
        #ifdef _DEBUG
            else
                ASSERT( 0 );
        #endif
        
            fvi.Close();
        }
        
        return ( S_FALSE );
    }
    
    //...

Notes

This class is a generic class - you can include it in any type of project - in MFC/ATL/WTL/API EXE or DLL or some other type applications, it has no dependencies. It compiles with both ANSI and UNICODE at warning level 4.

History

  • 15th July, 2003
    • Posted article
  • 27th July, 2003
    • Removed VOS_DOS_WINDOWS32 from DllGetVersion file type detection
    • Updated DllGetVersion to support DLLVERSIONINFO2 structure
  • 21st January, 2004
    • Added GetFileVersionMajor, GetFileVersionMinor, GetFileVersionBuild, GetFileVersionQFE functions
  • 29th March, 2004
    • Added GetProductVersionMajor, GetProductVersionMinor, GetProductVersionBuild, GetProductVersionQFE functions

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here