Konrad
Konrad

Reputation: 41027

Getting application version from within application

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 "Version X.Y.Z" displayed at runtime without having a separate variable somewhere that I'd have to keep in sync with my ProductVersion and FileVersion.

To clarify: yes this is a standard C++ Windows project. I am aware of the GetFileVersionInfo method but it seems silly to have to open the binary from within the version in memory just to query the version information - I'm sure I'm missing something obvious here :-)

Upvotes: 12

Views: 12521

Answers (4)

Remy Lebeau
Remy Lebeau

Reputation: 598309

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.

Upvotes: 4

OhadM
OhadM

Reputation: 4801

As already said there is no easy way.

You can find here a great working example (ATL free).

Upvotes: 0

davidm_uk
davidm_uk

Reputation: 768

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

Upvotes: 6

Superman
Superman

Reputation: 3081

If the OS is Windows, use the GetFileVersionInfo and VerQueryValue functions.

Upvotes: 7

Related Questions