How do I programmatically get the version of a DLL or EXE file?
Asked Answered
A

5

84

I need to get the product version and file version for a DLL or EXE file using Win32 native APIs in C or C++. I'm not looking for the Windows version, but the version numbers that you see by right-clicking on a DLL file, selecting "Properties", then looking at the "Details" tab. This is usually a four-part dotted version number x.x.x.x.

Automation answered 2/6, 2009 at 17:4 Comment(4)
Which language are you using?Saccharate
GetFileVersionInfo()Bait
Doesn't matter if he just wants Win32 API calls. Any language that supports calling system DLLs should be fine.Dupe
Edited to clarify that this is about C/C++.Waneta
D
116

You would use the GetFileVersionInfo API.

See Using Version Information on the MSDN site.

Sample:

DWORD  verHandle = 0;
UINT   size      = 0;
LPBYTE lpBuffer  = NULL;
DWORD  verSize   = GetFileVersionInfoSize( szVersionFile, &verHandle);

if (verSize != NULL)
{
    LPSTR verData = new char[verSize];

    if (GetFileVersionInfo( szVersionFile, verHandle, verSize, verData))
    {
        if (VerQueryValue(verData,"\\",(VOID FAR* FAR*)&lpBuffer,&size))
        {
            if (size)
            {
                VS_FIXEDFILEINFO *verInfo = (VS_FIXEDFILEINFO *)lpBuffer;
                if (verInfo->dwSignature == 0xfeef04bd)
                {

                    // Doesn't matter if you are on 32 bit or 64 bit,
                    // DWORD is always 32 bits, so first two revision numbers
                    // come from dwFileVersionMS, last two come from dwFileVersionLS
                    TRACE( "File Version: %d.%d.%d.%d\n",
                    ( verInfo->dwFileVersionMS >> 16 ) & 0xffff,
                    ( verInfo->dwFileVersionMS >>  0 ) & 0xffff,
                    ( verInfo->dwFileVersionLS >> 16 ) & 0xffff,
                    ( verInfo->dwFileVersionLS >>  0 ) & 0xffff
                    );
                }
            }
        }
    }
    delete[] verData;
}
Dupe answered 2/6, 2009 at 17:14 Comment(9)
int revision = HIWORD(verInfo->dwProductVersionLS); int build = LOWORD(verInfo->dwProductVersionLS);Rectal
I know it has been a while, but for newbies like me this is how you get the .exe filename: TCHAR szVersionFile[MAX_PATH]; GetModuleFileName(NULL, szVersionFile, MAX_PATH );Lilley
@Lilley Don't call yourself a newbie. I've been programming in MFC for 6 years thus far, and this helped me.Lots
edited this answer because it was calculating the version numbers wrong. From the MSDN docs for dwProductVersionMS: "The most significant 32 bits of the file's binary version number. This member is used with dwFileVersionLS to form a 64-bit value used for numeric comparisons." , so you use both of them to calculate the version number. First two (major / minor) are in versionMS and last two (revision / build) are in versionLS. It doesn't matter if you are in 32/64 bit, DWORD is always 32 bits.Anoxemia
Make sure to link to libversion.a for MingW. See here for copy-pastable example: pastebin.com/sYZCVpfwDollydolman
NULL should not be used with DWORDs (0 would be correct instead)Forestation
Have to add version.lib to additional linker dependences. Referencing Mincore.lib as official docs suggest didn't work for me.Brahma
How to get file version for MSI files, GetFileVersionInfoSize giving error 1812Repp
@Repp It is possible that a MSI file may not have that information block.Dupe
N
23

All these solutions did not work properly (with my system). I found out that each of the four parts of the version number are saved as a 16-bit value.

The first two numbers are saved in the 32-bit DWORD dwFileVersionMS, and the second two in dwFileVersionLS. So I edited your code at the output section like this:

    TRACE( "File Version: %d.%d.%d.%d\n",
        ( pFileInfo->dwFileVersionMS >> 16 ) & 0xffff,
        ( pFileInfo->dwFileVersionMS >>  0 ) & 0xffff,
        ( pFileInfo->dwFileVersionLS >> 16 ) & 0xffff,
        ( pFileInfo->dwFileVersionLS >>  0 ) & 0xffff
        );

And it works perfectly. The output is formatted like on my system:

major.minor.build.revision

Nalda answered 8/11, 2012 at 13:45 Comment(1)
How to get file version for MSI files, GetFileVersionInfoSize giving error 1812?Repp
A
20

You get this information using the version information APIs. Here is a sample:

void PrintFileVersion( TCHAR *pszFilePath )
{
    DWORD               dwSize              = 0;
    BYTE                *pbVersionInfo      = NULL;
    VS_FIXEDFILEINFO    *pFileInfo          = NULL;
    UINT                puLenFileInfo       = 0;

    // Get the version information for the file requested
    dwSize = GetFileVersionInfoSize( pszFilePath, NULL );
    if ( dwSize == 0 )
    {
        printf( "Error in GetFileVersionInfoSize: %d\n", GetLastError() );
        return;
    }

    pbVersionInfo = new BYTE[ dwSize ];

    if ( !GetFileVersionInfo( pszFilePath, 0, dwSize, pbVersionInfo ) )
    {
        printf( "Error in GetFileVersionInfo: %d\n", GetLastError() );
        delete[] pbVersionInfo;
        return;
    }

    if ( !VerQueryValue( pbVersionInfo, TEXT("\\"), (LPVOID*) &pFileInfo, &puLenFileInfo ) )
    {
        printf( "Error in VerQueryValue: %d\n", GetLastError() );
        delete[] pbVersionInfo;
        return;
    }

    // pFileInfo->dwFileVersionMS is usually zero. However, you should check
    // this if your version numbers seem to be wrong

    printf( "File Version: %d.%d.%d.%d\n",
        ( pFileInfo->dwFileVersionLS >> 24 ) & 0xff,
        ( pFileInfo->dwFileVersionLS >> 16 ) & 0xff,
        ( pFileInfo->dwFileVersionLS >>  8 ) & 0xff,
        ( pFileInfo->dwFileVersionLS >>  0 ) & 0xff
        );

    // pFileInfo->dwProductVersionMS is usually zero. However, you should check
    // this if your version numbers seem to be wrong.

    printf( "Product Version: %d.%d.%d.%d\n",
        ( pFileInfo->dwProductVersionLS >> 24 ) & 0xff,
        ( pFileInfo->dwProductVersionLS >> 16 ) & 0xff,
        ( pFileInfo->dwProductVersionLS >>  8 ) & 0xff,
        ( pFileInfo->dwProductVersionLS >>  0 ) & 0xff
        );

    delete[] pbVersionInfo;
}
Automation answered 2/6, 2009 at 17:22 Comment(2)
I think this is wrong. for file version 1.0.0.1 this function gives me "0.0.0.1". I ended up @Paddlefish 's answerInequity
There is a memory leak. pbVersionInfo is not released at the end of the function.Ress
P
5

This code shows the file version numbers correctly.

( pFileInfo->dwFileVersionMS >> 16 ) & 0xff,
( pFileInfo->dwFileVersionMS >> 0 ) & 0xff,
( pFileInfo->dwFileVersionLS >>  16 ) & 0xff,
( pFileInfo->dwFileVersionLS >>  0 ) & 0xff);
Paddlefish answered 15/10, 2012 at 14:16 Comment(4)
Can you provide some context to this answer? It seems to be incomplete. If it was a correction to another answer, please leave a comment on it, or edit that answer and it will be approved by a more experianced user.Karonkaross
this will definitely not work correctly, if the version includes any component greater than 255, e.g. 6.1.3709.2 The four components are 16-bit numbers, not 8-bit.Larina
This is not correct. The individual parts of the versions are 16-bit values. The code should be ( pFileInfo->dwFileVersionMS >> 16 ) & 0xffff, ( pFileInfo->dwFileVersionMS >> 0 ) & 0xffff, ( pFileInfo->dwFileVersionLS >> 16 ) & 0xffff, ( pFileInfo->dwFileVersionLS >> 0 ) & 0xffff);Canonist
As it was a long time ago !!! But I can share the solution. I then refused to receive information about executable files from the kernel driver. I then transferred this function to the service. The driver transmitted information about the start of the process and expected a resolution from the servicePaddlefish
E
4

The easiest way is to use the GetFileVersionInfoEx or GetFileVersionInfo API functions.

You can also do it from within your application resources as explained here.

Enrapture answered 2/6, 2009 at 17:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.