実行ファイルのバージョン情報はプロパティやバージョンダイアログで表示するはずである.
表示個所が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)
ファイルプロパティ言語情報取得