Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How might I retrieve the version number of a Windows EXE or DLL?

How to retrieve at runtime the version info stored in a Windows exe/dll? This info is manually set using a resource file.

like image 344
Valentin Galea Avatar asked Mar 03 '09 11:03

Valentin Galea


2 Answers

Here is a C++ way of doing it, using the standard Windows API functions:

try
{
    TCHAR szFileName[ MAX_PATH ];
    if( !::GetModuleFileName( 0, szFileName, MAX_PATH ) )
        throw __LINE__;

    DWORD nParam;
    DWORD nVersionSize = ::GetFileVersionInfoSize( szFileName, &nParam );
    if( !nVersionSize )
        throw __LINE__;

    HANDLE hMem = ::GetProcessHeap();
    if( !hMem )
        throw __LINE__;

    LPVOID lpVersionData = ::HeapAlloc( hMem, 0, nVersionSize );
    if( !lpVersionData )
        throw __LINE__;

    if( !::GetFileVersionInfo( szFileName, 0, nVersionSize, lpVersionData ) )
        throw __LINE__;

    LPVOID pVersionInfo;
    UINT nSize;
    if( !::VerQueryValue( lpVersionData, _T("\\"), &pVersionInfo, &nSize ) )
        throw __LINE__;

    VS_FIXEDFILEINFO *pVSInfo = (VS_FIXEDFILEINFO *)pVersionInfo;
    CString strVersion;
    strVersion.Format( _T(" version %i.%i.%i.%i"),
        pVSInfo->dwProductVersionMS >> 16,
        pVSInfo->dwProductVersionMS & 0xFFFF,
        pVSInfo->dwProductVersionLS >> 16,
        pVSInfo->dwProductVersionLS & 0xFFFF
        );
    GetDlgItem( IDC_ABOUT_VERSION )->SetWindowText( strAppName + strVersion );

    if( !HeapFree( hMem, 0, lpVersionData ) )
        throw __LINE__;
}
catch( int err )
{
    ASSERT( !err ); // always break on debug builds to inspect error codes and such

    DWORD dwErr = ::GetLastError();

    // handle memory cleanup...
}

Note that the catch part is purely educational - in a real situation you would properly cleanup after the memory allocation and actually use the error code!

like image 142
Valentin Galea Avatar answered Sep 28 '22 09:09

Valentin Galea


Valentin's answer is correct, but note commenter plinth's warning about the possibility of a memory leak.

I'm also not sure why you'd use ::HeapAlloc in this day and age.

Here is a snippet that uses new and boost::shared_array to do the same thing in what IMHO is a safer and cleaner way.

#include <boost/shared_array.hpp> 

//.....

DWORD   dwHandle;
DWORD   dwFileVersionInfoSize = GetFileVersionInfoSize((LPTSTR)lpszFileName, &dwHandle);

if (!dwFileVersionInfoSize)
         return FALSE;

// ensure our data will be deleted
boost::shared_array<BYTE> data(new BYTE[dwFileVersionInfoSize]); 
LPVOID const lpData = data.get(); 

//party on with lpData.... 
like image 30
Jim In Texas Avatar answered Sep 28 '22 08:09

Jim In Texas