65.9K
CodeProject 正在变化。 阅读更多。
Home

CFileVersionInfo - 获取文件版本信息

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.84/5 (50投票s)

2003年7月25日

CPOL

5分钟阅读

viewsIcon

2276137

downloadIcon

8862

用于获取文件版本信息的类

引言

您可以使用此类来确定任何具有版本信息资源的文件的完整文件版本信息,例如动态链接库(DLL)、可执行文件、字体文件、OCX 文件等,包括多语言版本信息块。此类封装了 GetFileVersionInfoGetFileVersionInfoSizeVerQueryValueVerLanguageName API 函数。请参见下面的示例图像

背景

在开发 DLL 文件时,我曾想在其中实现 DllGetVersion 函数(如果需要,它会返回 DLL 的版本,请参见 Platform SDK)。当然,我可以在实现中返回固定的版本号,但那样的话,即使只进行一次重新构建(我在那个项目中使用了版本自动增量),它们也会变得不正确。因此,我决定使用 API 版本信息函数——即从文件版本信息资源读取版本信息并每次在被请求时返回它——并实现了 CFileVersionInfo 类。

示例用法

在这个示例中,我们查询 Shell32.dll 的版本信息(我们将得到类似这样的格式:“6.0.2600.0”)以及它的公司名称字符串(我们将得到类似“Microsoft Corporation”的内容)

//...
#ifndef __VERINFO_H__
    #include < verinfo.h >
#endif
//...

CFileVersionInfo fvi;
if( fvi.Open( _T( "shell32.dll" ) )
{
    TCHAR szVer[ 512 ] = { 0 };
    ::wsprintf( szVer, 
        _T( "%d.%d.%d.%d" ),
        fvi.GetFileVersionMajor(),  // Major version
        fvi.GetFileVersionMinor(),  // Minor version
        fvi.GetFileVersionBuild(),  // Build number
        fvi.GetFileVersionQFE()     // QFE
    );

    /*
    VS_FIXEDFILEINFO vsffi = m_fvi.GetVSFFI();
    ::wsprintf( szVer, 
        _T( "%d.%d.%d.%d" ),
        HIWORD( vsffi.dwFileVersionMS ),  // Major version
        LOWORD( vsffi.dwFileVersionMS ),  // Minor version
        HIWORD( vsffi.dwFileVersionLS ),  // Build number
        LOWORD( vsffi.dwFileVersionLS )   // QFE
    );
    */
    
    ::SetWindowText( hWndVersion, szVer );

    if( fvi.QueryStringValue( VI_STR_COMPANYNAME, szVer, 512 ) )
        ::SetWindowText( hWndCompName, szVer );

//...

    fvi.Close();
}
//...

翻译支持

如果应用程序或 DLL 支持语言列表(多语言版本信息块),您可以使用此类来单独获取其中数据,而无需使用多个版本资源(针对每种语言),具体取决于语言标识符和代码页。

在示例应用程序中,提供了三种不同的语言和代码页字符串表版本块,您可以全部测试它们。请参阅选择前的图像(上方)和选择后的图像(下方)。

类成员

基类

  • 没有基类

然后,当你开始迭代 2(这是构建迭代的开始)时,你可能想要复制测试用例并将它们重新分类到迭代 2。这还允许对测试用例进行粒度跟踪,并允许你说某个测试用例在一个迭代中是准备好的,但在另一个迭代中不是。同样,如何做到这一点取决于你以及你希望如何报告。 “场景”部分提供了更多细节。

  • CFileVersionInfo( void ) - 构造一个 CFileVersionInfo 对象

操作

  • BOOL Open( IN LPCTSTR lpszFileName ) - 通过 lpszFileName 中指定的名称打开文件版本信息。
  • BOOL Open( IN HMODULE hModule )- 通过 hModule 中指定的句柄打开文件版本信息。
  • void Close( void ) - 关闭指定模块并释放由 Open 方法加载的资源。
  • BOOL IsValid( void ) - 查询类内部数据是否有效。

版本信息检索

  • BOOL QueryStringValue( IN LPCTSTR lpszString, OUT LPTSTR lpszValue, IN INT nBuf ) const - 检索 StringTable 结构中的值,并将其返回到 nBuf 大小的 lpszValue 缓冲区中。lpszString 名称必须是下一个函数描述中枚举的预定义字符串之一。例如:m_ver.QueryStringValue( _T( "Comments" ), szBuf, 512 );
    注意:最好使用第二个版本的此函数,如下所述。
  • BOOL QueryStringValue( IN INT nIndex, OUT LPTSTR lpszValue, IN INT nBuf ) const - 检索 StringTable 结构中的值,并将其返回到 nBuf 大小的 lpszValue 缓冲区中。nIndex 名称必须是以下预定义常量之一:
    • VI_STR_COMMENTS - Comments
    • VI_STR_COMPANYNAME - CompanyName
    • VI_STR_FILEDESCRIPTION - FileDescription
    • VI_STR_FILEVERSION - FileVersion
    • VI_STR_INTERNALNAME - InternalName
    • VI_STR_LEGALCOPYRIGHT - LegalCopyright
    • VI_STR_LEGALTRADEMARKS - LegalTrademarks
    • VI_STR_ORIGINALFILENAME - OriginalFilename
    • VI_STR_PRIVATEBUILD - PrivateBuild
    • VI_STR_PRODUCTNAME - ProductName
    • VI_STR_PRODUCTVERSION - ProductVersion
    • VI_STR_SPECIALBUILD - SpecialBuild
    • VI_STR_OLESELFREGISTER - OLESelfRegister

    例如:m_ver.QueryStringValue( VI_STR_SPECIALBUILD, szBuf, 512 );

  • const VS_FIXEDFILEINFO& GetVSFFI( void ) const - 检索打开的文件版本信息的 VS_FIXEDFILEINFO 结构的引用。
  • LPCTSTR GetVerStringName( IN INT nIndex ) - 返回数组中 nIndex 参数的版本字符串名称 - 该类包含一个版本信息字符串的 static 数组,每个值都可以通过索引访问。例如:m_ver.GetVerStringName( VI_STR_PRODUCTNAME ) 将返回指向 _T( "ProductName" ) string 的指针。
  • GetVersionMajor( void ) const - 获取主版本号
  • GetVersionMinor( void ) const - 获取次版本号
  • GetVersionBuild( void ) const - 获取构建版本号
  • GetVersionQFE( void ) const - 获取 QFE 版本号

静态成员

  • BOOL GetLIDName( IN WORD wLID, OUT LPTSTR lpszName, IN INT nBuf ) - 检索 wLID 语言标识符的描述 string,并将其返回到 nBuf 大小的 lpszName 缓冲区中。
  • BOOL GetCPName( IN WORD wCP, OUT LPCTSTR* ppszName ) - 检索 wCP 代码页标识符的描述 string,并将其返回到 nBuf 大小的 lpszName 缓冲区中。

翻译方法

  • BOOL SetTrans ( IN LANGID wLID /*= LANG_NEUTRAL*/, IN WORD wCP /*= VI_CP_UNICODE*/ ) - 设置要用于版本信息数据(如果存在)的语言标识符和代码页。
  • INT FindTrans( IN LANGID wLID, IN WORD wCP ) const - 在版本信息数据中查找翻译(语言标识符和代码页)(如果存在)。
  • BOOL SetTransIndex( IN UINT nIndex /*= 0*/ ) - 通过索引设置要在版本信息数据(如果存在)中使用的翻译。
  • DWORD GetTransByIndex( IN UINT nIndex ) const - 提取翻译数组(如果存在)中指定索引处的翻译(语言标识符和代码页)。

内联翻译方法

  • UINT GetTransCount( void ) const - 返回翻译的数量,即资源翻译数组中找到的语言和代码页标识符对的串联数量。
  • UINT GetCurTransIndex( void ) const - 返回版本资源翻译数组中当前设置的翻译索引。
  • LANGID GetLIDByIndex( IN UINT nIndex ) const - 提取数组(如果存在)中指定索引处的 langid-codepage 翻译对的语言标识符。
  • WORD GetCPByIndex( IN UINT nIndex ) const - 提取数组(如果存在)中指定索引处的 langid-codepage 翻译对的代码页标识符。
  • DWORD GetCurTrans( void ) const - 返回当前在类中设置为默认值的 langid-codepage 翻译对。
  • LANGID GetCurLID( void ) const - 返回当前在类中设置为默认值的语言标识符。
  • WORD GetCurCP( void ) const - 返回当前在类中设置为默认值的代码页。

全局函数

  • STDAPI_( HRESULT ) DllGetVersion( IN HMODULE hModule, OUT DLLVERSIONINFO* lpDVI ) - 您可以在任何 DLL 的导出 DllGetVersion 中使用此函数来执行繁重的工作——返回指向 DLLVERSIONINFO 结构的指针,其中填充了您的应用程序版本数据。它使用了 CFileVersionInfo 类。请参见其实现。
    //...
    #ifndef __VERINFO_H__
        #include < verinfo.h >
    #endif
    //...
    
    HRESULT STDAPICALLTYPE DllGetVersion( IN  HMODULE hModule, 
                                          OUT DLLVERSIONINFO* lpDVI )
    {
        if( hModule == NULL || 
            ::IsBadReadPtr( lpDVI, sizeof( DLLVERSIONINFO* ) ) )
        {
            ASSERT_RETURN( S_FALSE );
        }
        
        const DWORD cbSize = lpDVI->cbSize;
        
        if(
    #ifdef DLLVERSIONINFO2
            (
    #endif
            cbSize != sizeof( DLLVERSIONINFO  )
    #ifdef DLLVERSIONINFO2
            && cbSize != sizeof( DLLVERSIONINFO2 ) ) 
    #endif
            || ::IsBadWritePtr( lpDVI, cbSize ) )
        {
            ASSERT_RETURN( S_FALSE );
        }
        
        ::ZeroMemory( lpDVI, cbSize );
        lpDVI->cbSize = cbSize;
        
        CFileVersionInfo fvi;
        if( fvi.Open( hModule ) )
        {
            VS_FIXEDFILEINFO vsffi = fvi.GetVSFFI();
        
            if( vsffi.dwFileType == VFT_DLL ||
                vsffi.dwFileType == VFT_STATIC_LIB )
            {
                switch( vsffi.dwFileOS )
                {            
                case VOS__WINDOWS32:
                case VOS_NT_WINDOWS32:
                    lpDVI->dwPlatformID = DLLVER_PLATFORM_WINDOWS;
                    break;
                case VOS_NT:
                    lpDVI->dwPlatformID = DLLVER_PLATFORM_NT;
                    break;            
                default:
                    return ( S_FALSE );
                }
        
                lpDVI->dwMajorVersion = HIWORD( vsffi.dwFileVersionMS );
                lpDVI->dwMinorVersion = LOWORD( vsffi.dwFileVersionMS );
                lpDVI->dwBuildNumber  = HIWORD( vsffi.dwFileVersionLS );
        
            #ifdef DLLVERSIONINFO2
    
                if( cbSize == sizeof( DLLVERSIONINFO2 ) )
                {
                    DLLVERSIONINFO2* lpDVI2 = (DLLVERSIONINFO2*)lpDVI;
                    lpDVI2->ullVersion = MAKEDLLVERULL( 
                        lpDVI->dwMajorVersion,
                        lpDVI->dwMinorVersion,
                        lpDVI->dwBuildNumber ,
                        LOWORD( vsffi.dwFileVersionLS )
                    );
                }
        
            #endif
        
                return ( S_OK );
            }
        #ifdef _DEBUG
            else
                ASSERT( 0 );
        #endif
        
            fvi.Close();
        }
        
        return ( S_FALSE );
    }
    
    //...

注释

此类是一个通用类——您可以将其包含在任何类型的项目中——MFC/ATL/WTL/API EXE 或 DLL 或其他类型的应用程序中,它没有任何依赖项。它可以在警告级别 4 下使用 ANSI 和 UNICODE 进行编译。

历史

  • 2003年7月15日
    • 发布文章
  • 2003年7月27日
    • DllGetVersion 文件类型检测中移除了 VOS_DOS_WINDOWS32
    • 更新了 DllGetVersion 以支持 DLLVERSIONINFO2 结构
  • 2004年1月21日
    • 添加了 GetFileVersionMajorGetFileVersionMinorGetFileVersionBuildGetFileVersionQFE 函数
  • 2004年3月29日
    • 添加了 GetProductVersionMajorGetProductVersionMinorGetProductVersionBuildGetProductVersionQFE 函数
© . All rights reserved.