如何通过编程获取DLL或EXE文件的版本?

84

我需要使用C或C++中的Win32本地API获取DLL或EXE文件的产品版本和文件版本。我是在寻找Windows版本,而是要获取您通过右键单击DLL文件,在选择“属性”,然后查看“详细信息”选项卡时看到的版本号。这通常是一个由四部分组成的带点版本号x.x.x.x。


你正在使用哪种编程语言? - overslacked
GetFileVersionInfo() - Matt Schmidt
7
只要他只需要 Win32 API 调用,所使用的编程语言支持调用系统 DLL,就可以了。 - crashmstr
编辑以澄清这是关于C/C++。 - JSBձոգչ
6个回答

115
您可以使用 GetFileVersionInfo API。
请参阅 MSDN 网站上的 Using Version Information
示例:
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;
}

2
int revision = HIWORD(verInfo->dwProductVersionLS); int build = LOWORD(verInfo->dwProductVersionLS); - Igor Jerosimić
8
我知道这已经过去一段时间了,但对于像我这样的新手,这是获取.exe文件名的方法:TCHAR szVersionFile[MAX_PATH]; GetModuleFileName(NULL, szVersionFile, MAX_PATH ); - BurninatorDor
1
@BurninatorDor 不要自称为新手。我已经在MFC编程方面工作了6年,这对我很有帮助。 - Neil
2
编辑了这个答案,因为它计算版本号时出错了。根据MSDN文档中的dwProductVersionMS:“文件二进制版本号的最高32位。此成员与dwFileVersionLS一起用于形成用于数字比较的64位值。” 因此,您需要同时使用它们来计算版本号。前两个(主/次)在versionMS中,后两个(修订/构建)在versionLS中。无论您是在32位/64位中,DWORD始终为32位。 - mgrandi
1
不应该在DWORD中使用NULL(应该使用0)。 - M.M
显示剩余4条评论

22

所有这些解决方案都无法正常工作(对于我的系统来说)。我发现版本号的四个部分都保存为16位值。

前两个数字保存在32位DWORD dwFileVersionMS中,后两个数字保存在dwFileVersionLS中。因此,我在输出部分像这样编辑了您的代码:

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

它完美地运行。输出格式与我的系统相同:

主版本.次版本.构建版本.修订版本


如何获取MSI文件的文件版本,GetFileVersionInfoSize出现错误1812? - user3664223

20
你可以使用版本信息API来获取这些信息。以下是一个示例:
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;
}

3
我认为这是错误的。对于文件版本1.0.0.1,该函数给出了“0.0.0.1”。我最终采用了@Vasya的答案。 - liorda
1
存在内存泄漏问题。pbVersionInfo在函数结束时没有被释放。 - Dmytro Ovdiienko

6

虽然这个链接可能回答了问题,但最好在这里包含答案的关键部分,并提供链接作为参考。仅有链接的答案如果链接页面发生变化,可能会变得无效。- 来自审查 - undefined

5

这段代码可以正确显示文件版本号。

( pFileInfo->dwFileVersionMS >> 16 ) & 0xff,
( pFileInfo->dwFileVersionMS >> 0 ) & 0xff,
( pFileInfo->dwFileVersionLS >>  16 ) & 0xff,
( pFileInfo->dwFileVersionLS >>  0 ) & 0xff);

4
你能提供一些关于这个回答的背景信息吗?它似乎不完整。如果这是对另一个回答的更正,请在其下留言,或编辑该回答,它将由更有经验的用户批准。 - Deanna
1
如果版本号包括大于255的任何组件(例如6.1.3709.2),则这肯定不能正常工作。这四个组件都是16位数字,而不是8位数字。 - Spike0xff
这不正确。版本的各个部分是16位值。代码应该是( pFileInfo->dwFileVersionMS >> 16 ) & 0xffff, ( pFileInfo->dwFileVersionMS >> 0 ) & 0xffff, ( pFileInfo->dwFileVersionLS >> 16 ) & 0xffff, ( pFileInfo->dwFileVersionLS >> 0 ) & 0xffff); - DaveCleland
虽然这是很久以前的事情了!!!但我可以分享解决方案。我拒绝从内核驱动程序接收可执行文件的信息。然后我将此功能转移到了服务中。驱动程序传输有关进程启动的信息,并期望从服务获得解决方案。 - Vasya

4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接