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:
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(),
fvi.GetFileVersionMinor(),
fvi.GetFileVersionBuild(),
fvi.GetFileVersionQFE()
);
::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:
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):
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
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
- 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