Last Updated 2005/08/19
Visual C++ API
バージョン取得
2005/08/19

実行ファイルのバージョン情報はプロパティやバージョンダイアログで表示するはずである.
表示個所が2箇所あるということは,変更した場合も2箇所変更が必要になってしまう.
(Version リソースの変更とバージョンダイアログリソースの変更)
Version リソースの変更のみでバージョンダイアログは Version リソースの値を参照するようにすれば変更個所は1つでミスもなくなる.


GetModuleFileName() してから GetFileVersionInfoSize(), GetFileVersionInfo() すればVersion リソースの値が取得可能である.その値を元にバージョンダイアログの表示を作成すればよい.

CString strVer;
char szFullPath[MAX_PATH];
GetModuleFileName(NULL, szFullPath, sizeof(szFullPath));
DWORD dwZero = 0;
DWORD dwVerInfoSize = GetFileVersionInfoSize(szFullPath, &dwZero);
if( dwVerInfoSize ) {
    unsigned char *pVffInfo;
    pVffInfo = new unsigned char[dwVerInfoSize];
    if( pVffInfo == NULL )
        return FALSE;
    GetFileVersionInfo(szFullPath, dwZero, dwVerInfoSize, pVffInfo);

    void *pvVersion;
    UINT VersionLen;
    VerQueryValue(pVffInfo, TEXT("\\StringFileInfo\\041104b0\\ProductVersion"), &pvVersion, &VersionLen);

    strVer = AfxGetAppName();
    strVer += "  ";
    strVer += (char*)pvVersion;
    SetDlgItemText(IDC_AppNameVersion, strVer);

    delete [] pVffInfo;
}


GetFileVersionInfoSize() などを使用するには version.lib をリンクしなければならない.




また,Version リソースの他の情報を得る為には以下の様にする.

HINSTANCE hI = AfxGetResourceHandle();
HRSRC hR = FindResourceEx(hI, RT_VERSION, MAKEINTRESOURCE(VS_VERSION_INFO), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));




似たようなコードだが参考の為以下も掲載する.

BOOL CAboutDlg::OnInitDialog() 
{
    // 現在の実行モジュールを含む EXE ファイルのフル・パスを取得
    char szModuleName[_MAX_PATH + 1];
    int nRet = ::GetModuleFileName( NULL, szModuleName, _MAX_PATH );
    ASSERT( nRet );

    // ファイルのバージョン情報のサイズを取得
    DWORD dwSize = 0;
    DWORD dwReserved;
    LPVOID lpBuff = NULL;
    dwSize = ::GetFileVersionInfoSize( szModuleName, &dwReserved );
    ASSERT( dwSize > 0 );
    // バージョン情報を受け取るバッファを準備
    lpBuff = malloc( dwSize );
    ASSERT( lpBuff );
    if( lpBuff ) {
        // ファイルのバージョン情報を取得
        BOOL bRet = ::GetFileVersionInfo( szModuleName, 0, dwSize, lpBuff );
        ASSERT( bRet );
        if( bRet ) {
            UINT    dwLen;
            LPWORD  lpWord;
            DWORD   dwLangAndCharSet;

            // 言語・キャラクタセット変換テーブルを取得
            bRet = ::VerQueryValue( lpBuff, "\\VarFileInfo\\Translation", (void **)&lpWord, &dwLen );
            ASSERT( bRet );
           if( bRet ) {
               // lpWord[0] は言語セット lpWord[1] はキャラクタセット
               dwLangAndCharSet = MAKELONG( lpWord[1], lpWord[0] );

               LPTSTR  lpStr;
               char    szKey[256];

               // 製品名
               sprintf( szKey, "\\StringFileInfo\\%08\\%s", dwLangAndCharSet, "ProductName" );
               bRet = ::VerQueryValue( lpBuff, szKey,  (void **)&lpStr, &dwLen );
               if( bRet ) {
                   m_strProductName = lpStr;  
                   // m_strProductName は CAboutDlg のメンバ変数
               }
               // 製品バージョン
               sprintf( szKey, "\\StringFileInfo\\%08x\\%s", dwLangAndCharSet, "ProductVersion" );
               bRet = ::VerQueryValue( lpBuff, szKey, (void **)&lpStr, &dwLen );
               if( bRet ) {
                   m_strProductVersion.Format( "Version %s", lpStr );
                   // m_strProductVersion は CAboutDlg のメンバ変数
               }
               // その他の処理
           }
       }
       free( lpBuff );
    }

    CDialog::OnInitDialog();

    return TRUE;
}


言語・キャラクタセットの変換テーブルを取得するところがポイント.

アプリケーション側で確保および解放しなければならないメモリは,バージョン情報を受け取るためのバッファ( GetFileVersionInfo() に渡す LPVOID lpBuff)だけ.
VerQueryValue() の3番目の引数は,当該個別情報のアドレスを受け取る変数のアドレスである.
VerQueryValue() は当該個別情報のために新たなバッファを確保せず1番目の引数であるバージョン情報全体の中から適切なアドレスを(もしあれば)返す.


参照
バージョンの取得(DLL)
ファイルプロパティ言語情報取得
前後のTips
バージョン取得

DSS ProgrammingTipsCGI Ver1.02