Is there a simple way of obtaining the application version information from the resource file at runtime?
Effectively what I\'d like to do is be able to have a \"Ve
If the OS is Windows, use the GetFileVersionInfo
and VerQueryValue
functions.
As already said there is no easy way.
You can find here a great working example (ATL free).
The only officially supported approach is to use GetFileVersionInfo()
and VerQueryValue()
. However, as you have noticed, GetFileVersionInfo()
requires you to pass in the filename of the executable. There is a reason for this. Although it is simple to obtain the running process's filename using GetModuleFileName()
, it is not the most efficient option, especially if the executable is running from a remote share, and it is not even guaranteed to be accurate if the executable has been modified on the HDD after the process has started running.
You can access the version info of the process that is already running in memory, by calling FindResource()
to locate the process's RT_VERSION
resource, then use LoadResource()
and LockResource()
to obtain a pointer to its data. It is tempting to then pass that pointer as the pBlock
parameter of VerQueryValue()
, but beware because doing so can crash your code! If you access the RT_VERSION
resource directly then you are better off not using VerQueryValue()
at all. The format of the RT_VERSION resource is documented, so you can parse the raw data manually, it is not very difficult.
I don't believe that there's an easier way (than opening the file and using GetFileVersionInfo and VerQueryValue). I use the following code, in case it's helpful:
static CString GetProductVersion()
{
CString strResult;
char szModPath[ MAX_PATH ];
szModPath[ 0 ] = '\0';
GetModuleFileName( NULL, szModPath, sizeof(szModPath) );
DWORD dwHandle;
DWORD dwSize = GetFileVersionInfoSize( szModPath, &dwHandle );
if( dwSize > 0 )
{
BYTE* pbBuf = static_cast<BYTE*>( alloca( dwSize ) );
if( GetFileVersionInfo( szModPath, dwHandle, dwSize, pbBuf ) )
{
UINT uiSize;
BYTE* lpb;
if( VerQueryValue( pbBuf,
"\\VarFileInfo\\Translation",
(void**)&lpb,
&uiSize ) )
{
WORD* lpw = (WORD*)lpb;
CString strQuery;
strQuery.Format( "\\StringFileInfo\\%04x%04x\\ProductVersion", lpw[ 0 ], lpw[ 1 ] );
if( VerQueryValue( pbBuf,
const_cast<LPSTR>( (LPCSTR)strQuery ),
(void**)&lpb,
&uiSize ) && uiSize > 0 )
{
strResult = (LPCSTR)lpb;
}
}
}
}
return strResult;
}
David