如何获得DLL或EXE文件的语言信息?
例如:我们在DLL或者EXE的右键的属性页里,版本选项卡中能够显示出语言信息,如:英语(美国)、中文(中国)等等。

解决方案 »

  1.   

    我指的是通过编程的方式获得指定DLL或者EXE文件的语言信息,也就是说要实现类似于下面这样的函数:
    CString GetModuleLanguage(const CString &cstrModulePath);
      

  2.   

    不就是去读文件的属性吗,msdn
      

  3.   

    没有啊!BOOL GetFileAttributesEx(
      LPCTSTR lpFileName,                   // file or directory name
      GET_FILEEX_INFO_LEVELS fInfoLevelId,  // attribute class
      LPVOID lpFileInformation              // attribute information 
    );typedef struct _WIN32_FILE_ATTRIBUTE_DATA{ 
      DWORD      dwFileAttributes; 
      FILETIME   ftCreationTime; 
      FILETIME   ftLastAccessTime; 
      FILETIME   ftLastWriteTime; 
      DWORD      nFileSizeHigh; 
      DWORD      nFileSizeLow; 
    } WIN32_FILE_ATTRIBUTE_DATA, *LPWIN32_FILE_ATTRIBUTE_DATA;在哪里呀?
      

  4.   

    其实我研究了一下,通过GetFileVersionInfo()函数可以辗转得到语言代码页信息(数字的),但是不知道如何通过语言代码页信息如何转化为具体的类似于“英语(美国)、中文(中国)”的字符串信息,而且,我想要的效果是:假如目标文件是英文语言的,那么在中文操作系统下得到的是“英语(美国)”,而在英文操作系统下就得到“English (United States)”,也就是说要得到相应的操作系统语言环境下能读得懂的字符串。望高手们指教!
      

  5.   

    VerQueryValue(pVerInfo, "\\VarFileInfo\\Translation", ....
    得到语言信息,GetLocaleInfo得到操作系统下的字符串。
    自己看MSDN吧。
      

  6.   

    to  verybigbug() 
    Thanks!正在研究中...
      

  7.   

    CString GetModuleLanguage(const CString &cstrModulePath);
    学习阿卓
      

  8.   

    就快搞定啦,待会儿给出正解,多谢verybigbug()!
      

  9.   

    http://www.codeproject.com/file/VersionInfo.asp
    就有语言这个信息。为方便大家贴出来。
    /////////////////////////////////////////////////////////////////////////////
    /* 
    DESCRIPTION:
    CFileVersionInfo - Class for getting file version information
    http://www.codeproject.com/file/VersionInfo.aspNOTES:
    Copyright(C) Armen Hakobyan, 2003
    mailto:[email protected]

    VERSION HISTORY:
    25 Jul 2003 - Posted the article
    27 Jul 2003 - Added DLLVERSIONINFO2 support to DllGetVersion
    21 Jan 2004 - Added GetFileVersionMajor, GetFileVersionMinor,
      GetFileVersionBuild, GetFileVersionQFE functions
    29 Jan 2004 - Added GetProductVersionMajor, GetProductVersionMinor,
      GetProductVersionBuild, GetProductVersionQFE functions
    */
    /////////////////////////////////////////////////////////////////////////////#include "stdafx.h"
    #include "verinfo.h"/////////////////////////////////////////////////////////////////////////////
    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 );
    }/////////////////////////////////////////////////////////////////////////////
    // HIWORD( ffi.dwFileVersionMS ) - major
    // LOWORD( ffi.dwFileVersionMS ) - minor
    // HIWORD( ffi.dwFileVersionLS ) - build
    // LOWORD( ffi.dwFileVersionLS ) - QFE
    /////////////////////////////////////////////////////////////////////////////CFileVersionInfo::CFileVersionInfo( void )
    : m_lpbyVIB( NULL )
    {
    Close();
    }CFileVersionInfo::~CFileVersionInfo( void )
    {
    Close();
    }LPCTSTR CFileVersionInfo::s_ppszStr[] = { 
    _T( "Comments" ), _T( "CompanyName" ),      
    _T( "FileDescription" ), _T( "FileVersion" ),
    _T( "InternalName" ), _T( "LegalCopyright" ),
    _T( "LegalTrades" ), _T( "OriginalFilename" ),
    _T( "PrivateBuild" ), _T( "ProductName" ),
    _T( "ProductVersion" ), _T( "SpecialBuild" ),
    _T( "OLESelfRegister" )
    };
      

  10.   

    ////////////////////////////////////////////////////////////////////////////////
    // ImplementationBOOL CFileVersionInfo::Open( IN HINSTANCE hInstance )
    {
    if( hInstance == NULL )
    ASSERT_RETURN( FALSE ); TCHAR szFileName[ MAX_PATH ] = { 0 };
    if( ::GetModuleFileName( hInstance, szFileName, MAX_PATH ) )
    return Open( szFileName ); return FALSE;
    };BOOL CFileVersionInfo::Open( IN LPCTSTR lpszFileName )
    {
    if( lpszFileName == NULL )
    ASSERT_RETURN( FALSE ); Close();
    if( !GetVersionInfo( lpszFileName ) || !QueryVersionTrans() )
    Close(); return m_bValid;
    };BOOL CFileVersionInfo::GetVersionInfo( IN LPCTSTR lpszFileName )
    {
    DWORD dwDummy = 0;
    DWORD dwSize  = ::GetFileVersionInfoSize( 
    const_cast< LPTSTR >( lpszFileName ), &dwDummy // Set to 0
    ); if ( dwSize > 0 )
    {
    m_lpbyVIB = (LPBYTE)malloc( dwSize ); if ( m_lpbyVIB != NULL && 
    ::GetFileVersionInfo( const_cast< LPTSTR >( lpszFileName ), 
    0, dwSize, m_lpbyVIB ) )
    {
    UINT   uLen    = 0;
    LPVOID lpVSFFI = NULL;

    if ( ::VerQueryValue( m_lpbyVIB, _T( "\\" ), (LPVOID*)&lpVSFFI, &uLen ) )
    {
    ::CopyMemory( &m_vsffi, lpVSFFI, sizeof( VS_FIXEDFILEINFO ) );
    m_bValid = ( m_vsffi.dwSignature == VS_FFI_SIGNATURE );
    }
    }
    } return m_bValid;
    }BOOL CFileVersionInfo::QueryVersionTrans( void )
    {
    if( m_bValid == FALSE )
    ASSERT_RETURN( FALSE ); UINT   uLen  = 0;
    LPVOID lpBuf = NULL;
      
    if( ::VerQueryValue( m_lpbyVIB, _T( "\\VarFileInfo\\Translation" ), (LPVOID*)&lpBuf, &uLen ) )
    {
    m_lpdwTrans = (LPDWORD)lpBuf;
    m_nTransCnt = ( uLen / sizeof( DWORD ) );
    }
    return (BOOL)( m_lpdwTrans != NULL );
    }void CFileVersionInfo::Close( void )
    {
    m_nTransCnt  = 0;
    m_nTransCur  = 0;
    m_bValid  = FALSE;
    m_lpdwTrans  = NULL;

    ::ZeroMemory( &m_vsffi, sizeof( VS_FIXEDFILEINFO ) );
    _free( m_lpbyVIB );
    }BOOL CFileVersionInfo::QueryStringValue( IN  LPCTSTR lpszItem,
     OUT LPTSTR  lpszValue, 
     IN  INT     nBuf ) const
    {
    if( m_bValid  == FALSE || lpszItem == NULL )
    ASSERT_RETURN( FALSE );

    if( lpszValue != NULL && nBuf <= 0 )
    ASSERT_RETURN( FALSE ); ::ZeroMemory( lpszValue, nBuf * sizeof( TCHAR ) ); TCHAR szSFI[ MAX_PATH ] = { 0 };
    ::wsprintf( szSFI, _T( "\\StringFileInfo\\%04X%04X\\%s" ), 
    GetCurLID(), GetCurCP(), lpszItem ); BOOL   bRes    = FALSE;
    UINT   uLen    = 0;
    LPTSTR lpszBuf = NULL; if( ::VerQueryValue( m_lpbyVIB, (LPTSTR)szSFI, (LPVOID*)&lpszBuf, &uLen ) )
    {
    if( lpszValue != NULL && nBuf > 0 )
    bRes = (BOOL)( ::lstrcpyn( lpszValue, lpszBuf, nBuf ) != NULL );
    else
    bRes = TRUE;
    }

    return ( bRes );
    }BOOL CFileVersionInfo::QueryStringValue( IN  INT    nIndex, 
     OUT LPTSTR lpszValue,
     IN  INT    nBuf ) const
    {
    if( nIndex < VI_STR_COMMENTS || 
    nIndex > VI_STR_OLESELFREGISTER ) 

    ASSERT_RETURN( FALSE );
    }
    return QueryStringValue( s_ppszStr[ nIndex ], lpszValue, nBuf );
    }LPCTSTR CFileVersionInfo::GetVerStringName( IN INT nIndex )

    if( nIndex < VI_STR_COMMENTS || 
    nIndex > VI_STR_OLESELFREGISTER ) 

    ASSERT_RETURN( FALSE );
    }
    return (LPCTSTR)s_ppszStr[ nIndex ];
    }INT CFileVersionInfo::FindTrans( IN LANGID wLID,
     IN WORD   wCP ) const
    {
    if( m_bValid == FALSE )
    ASSERT_RETURN( -1 ); for( UINT n = 0; n < m_nTransCnt; n++ )
    {
    if( LOWORD( m_lpdwTrans[ n ] ) == wLID && 
    HIWORD( m_lpdwTrans[ n ] ) == wCP  )
    {
    return n;
    }
    }
    return -1;
    }BOOL CFileVersionInfo::SetTrans( IN LANGID wLID /*LANG_NEUTRAL*/, 
     IN WORD   wCP  /*WSLVI_CP_UNICODE*/ )
    {
    if( m_bValid == FALSE )
    ASSERT_RETURN( FALSE ); if( GetCurLID() == wLID && GetCurCP() == wCP )
    return TRUE; INT nPos = FindTrans( wLID, wCP );
    if( nPos != -1 ) m_nTransCur = nPos; return ( m_nTransCur == (UINT)nPos );
    }DWORD CFileVersionInfo::GetTransByIndex( IN UINT nIndex ) const
    {
    if( m_bValid == FALSE || nIndex < 0 || nIndex > m_nTransCnt )
    ASSERT_RETURN( 0 ); return m_lpdwTrans[ nIndex ];
    }BOOL CFileVersionInfo::SetTransIndex( IN UINT nIndex /*0*/ )
    {
    if( m_bValid == FALSE )
    ASSERT_RETURN( FALSE ); if( m_nTransCur == nIndex )
    return TRUE; if( nIndex >= 0 && nIndex <= m_nTransCnt )
    m_nTransCur = nIndex;

    return ( m_nTransCur == nIndex );
    }/////////////////////////////////////////////////////////////////////////////
    // Static members// If the LID identifier is unknown, it returns a 
    // default string ("Language Neutral"):BOOL CFileVersionInfo::GetLIDName( IN  WORD   wLID, 
       OUT LPTSTR lpszName, 
       IN  INT    nBuf )
    {
    if( lpszName == NULL || nBuf <= 0 )
    ASSERT_RETURN( FALSE ); return (BOOL)::VerLanguageName( wLID, lpszName, nBuf );
    }// If the CP identifier is unknown, it returns a 
    // default string ("Unknown"):BOOL CFileVersionInfo::GetCPName( IN  WORD    wCP,
      OUT LPCTSTR* ppszName )
    {
    if( ppszName == NULL )
    ASSERT_RETURN( FALSE ); BOOL bRes = TRUE;
    *ppszName  = NULL; switch ( wCP )
    {
    case VI_CP_ASCII:  *ppszName = _T( "7-bit ASCII" ); break;
    case VI_CP_JAPAN:  *ppszName = _T( "Japan (Shift ?JIS X-0208)" );break;
    case VI_CP_KOREA:  *ppszName = _T( "Korea (Shift ?KSC 5601)" ); break;
    case VI_CP_TAIWAN:  *ppszName = _T( "Taiwan (Big5)" ); break;
    case VI_CP_UNICODE:  *ppszName = _T( "Unicode" ); break;
    case VI_CP_LATIN2:  *ppszName = _T( "Latin-2 (Eastern European)" );break;
    case VI_CP_CYRILLIC: *ppszName = _T( "Cyrillic" ); break;
    case VI_CP_MULTILNG: *ppszName = _T( "Multilingual" ); break;
    case VI_CP_GREEK:  *ppszName = _T( "Greek" ); break;
    case VI_CP_TURKISH:  *ppszName = _T( "Turkish" ); break;
    case VI_CP_HEBREW:  *ppszName = _T( "Hebrew" ); break;
    case VI_CP_ARABIC:  *ppszName = _T( "Arabic" ); break;
    default:  *ppszName = _T( "Unknown" ); bRes = FALSE; break;
    }
    return bRes;
    }
    /////////////////////////////////////////////////////////////////////////////
      

  11.   

    /////////////////////////////////////////////////////////////////////////////
    /* 
    DESCRIPTION:
    CFileVersionInfo - Class for getting file version information
    http://www.codeproject.com/file/VersionInfo.aspNOTES:
    Copyright(C) Armen Hakobyan, 2003
    mailto:[email protected]

    VERSION HISTORY:
    25 Jul 2003 - Posted the article
    27 Jul 2003 - Added DLLVERSIONINFO2 support to DllGetVersion
    21 Jan 2004 - Added GetFileVersionMajor, GetFileVersionMinor,
      GetFileVersionBuild, GetFileVersionQFE functions
    29 Jan 2004 - Added GetProductVersionMajor, GetProductVersionMinor,
      GetProductVersionBuild, GetProductVersionQFE functions
    */
    /////////////////////////////////////////////////////////////////////////////#ifndef __VERINFO_H__ 
    #define __VERINFO_H__#if defined( _MSC_VER ) && ( _MSC_VER >= 1020 )
    #pragma once
    #endif/////////////////////////////////////////////////////////////////////////////#ifndef _INC_SHLWAPI
    #include < Shlwapi.h >
    #endif
    #pragma comment( lib, "shlwapi.lib" )#ifndef VER_H
    #include < WinVer.h >
    #endif
    #pragma comment( lib, "Version.lib " )#ifndef _T
    #ifndef _INC_TCHAR
    #include < TChar.h >
    #endif
    #endif#ifndef ASSERT
    #ifndef _INC_CRTDBG
    #include < CrtDbg.h >
    #endif
    #define ASSERT( x ) _ASSERTE( x )
    #endif///////////////////////////////////////////////////////////////////////////////#define _wslPackVersion( major, minor ) MAKELONG( minor, major )#ifndef _free
    #define _free( p ) { if( p != NULL ){ free( p ); p = NULL; } }
    #endif#ifndef ASSERT_RETURN
    #define ASSERT_RETURN( x ) { ASSERT( 0 ); return x; }
    #endif/////////////////////////////////////////////////////////////////////////////#ifndef DLLVER_MAJOR_MASK typedef struct _DLLVERSIONINFO2 {
    DLLVERSIONINFO info1;
    DWORD dwFlags; // No flags currently defined
    ULONGLONG ullVersion;
    } DLLVERSIONINFO2;#endif // DLLVER_MAJOR_MASK#ifndef MAKEDLLVERULL #define MAKEDLLVERULL( major, minor, build, qfe )\
    ( ( (ULONGLONG)(major) << 48 ) |  \
    (   (ULONGLONG)(minor) << 32 ) |  \
    (   (ULONGLONG)(build) << 16 ) |  \
    (   (ULONGLONG)(  qfe) <<  0 ) )#endif // MAKEDLLVERULL
    /////////////////////////////////////////////////////////////////////////////STDAPI_( HRESULT ) DllGetVersion( IN HMODULE hModule, OUT DLLVERSIONINFO* lpDVI );/////////////////////////////////////////////////////////////////////////////typedef enum _VI_CP {
    VI_CP_ASCII = 0, // 7-bit ASCII 
    VI_CP_JAPAN = 932, // Japan (Shift - JIS X-0208) 
    VI_CP_KOREA = 949, // Korea (Shift - KSC 5601) 
    VI_CP_TAIWAN = 950, // Taiwan (Big5) 
    VI_CP_UNICODE = 1200, // Unicode 
    VI_CP_LATIN2 = 1250, // Latin-2 (Eastern European) 
    VI_CP_CYRILLIC = 1251, // Cyrillic 
    VI_CP_MULTILNG = 1252, // Multilingual 
    VI_CP_GREEK = 1253, // Greek 
    VI_CP_TURKISH = 1254, // Turkish 
    VI_CP_HEBREW = 1255, // Hebrew 
    VI_CP_ARABIC = 1256 // Arabic 
    } VI_CP;
      

  12.   

    http://www.codeproject.com/file/VersionInfo.asp
    太累了,还没贴完,自己去看吧。有例子程序的。
      

  13.   

    pepsi1980(这只老鼠不会游泳) ( ) 赞一个.
      

  14.   

    正解:CString GetModuleLanguage(LPCTSTR lpszModulePath)
    {
    HMODULE hModule = NULL; hModule = ::LoadLibrary(lpszModulePath); if (NULL == hModule)
    {
    return _T("");
    } // Get the version information size for allocate the buffer
    DWORD dwHandle = 0;
    DWORD dwDataSize = 
    ::GetFileVersionInfoSize((LPTSTR)lpszModulePath, &dwHandle); if (0 == dwDataSize)
    {
    ::FreeLibrary(hModule);
    return _T("");
    } LPBYTE  lpVersionData = NULL; // Allocate buffer and retrieve version information
    lpVersionData = new BYTE[dwDataSize];
    if (NULL == lpVersionData)
    {
    ::FreeLibrary(hModule);
    return _T("");
    } if (!::GetFileVersionInfo((LPTSTR)lpszModulePath, dwHandle, dwDataSize, 
      (void **)lpVersionData))
    {
    delete[] lpVersionData;
    ::FreeLibrary(hModule);
    return _T("");
    } // Retrieve the first language and character-set identifier
    UINT nQuerySize = 0;
    DWORD *pTransTable = NULL; if (!::VerQueryValue(lpVersionData, _T("\\VarFileInfo\\Translation"),
     (void **)&pTransTable, &nQuerySize))
    {
    delete[] lpVersionData;
    ::FreeLibrary(hModule);
    return _T("");
    } TCHAR szBuffer[MAX_PATH] = {_T('\0')}; if (!::VerLanguageName(
    LOWORD(pTransTable[0]), 
    szBuffer, 
    sizeof(szBuffer) / sizeof(szBuffer[0]) - 1))
    {
    delete[] lpVersionData;
    ::FreeLibrary(hModule);
    return _T("");
    } delete[] lpVersionData;

    ::FreeLibrary(hModule);

    return CString(szBuffer);
    }