Visual Studioなどで開発していると、バージョン番号はリソースで値を管理することになります。
リソースで設定すると、内容がEXEファイルのプロパティの詳細タブでも確認できるようになるので便利ですね。
このような情報は1か所で管理するべきなので、バージョン情報画面などを出した場合リソースから値を取得する必要があります。
C#の場合はこちら↓
リソースからバージョンを取得する
TCHAR fileName[ MAX_PATH + 1 ]; DWORD size; BYTE* pVersion; VS_FIXEDFILEINFO* pFileInfo; UINT queryLen; CString fileVersion; ::GetModuleFileName( NULL, fileName, sizeof( fileName ) ); size = ::GetFileVersionInfoSize( fileName, NULL ); pVersion = new BYTE[ size ]; if( ::GetFileVersionInfo( fileName, NULL, size, pVersion ) ) { ::VerQueryValue( pVersion, _T( "\\" ), (void**)&pFileInfo, &queryLen ); fileVersion.Format( _T( "%d.%d.%d.%d" ), HIWORD( pFileInfo->dwFileVersionMS ), LOWORD( pFileInfo->dwFileVersionMS ), HIWORD( pFileInfo->dwFileVersionLS ), LOWORD( pFileInfo->dwFileVersionLS ) ); } delete[] pVersion;
実行ファイルのファイル名を取得 (8行目)
GetModuleFileName関数を使って実行ファイルのファイル名を取得します。
第1引数にNULLを指定すると現在のプロセスを作成するために使われたファイル名が取得できます。
バージョン情報を格納する為のバッファーサイズを取得 (10行目)
GetFileVersionInfoSize関数を使って必要なバッファーサイズを取得します。
バッファーを確保しバージョン情報リソースを取得 (11~12行目)
バッファーを確保してからGetFileVersionInfo関数を使ってリソースを取得します。
バージョン情報から値を取得 (13行目)
VerQueryValue関数を使ってリソースからバージョン情報を取得します。
取得できるVS_FIXEDFILEINFO構造体は以下の通りです。
typedef struct tagVS_FIXEDFILEINFO { DWORD dwSignature; /* e.g. 0xfeef04bd */ DWORD dwStrucVersion; /* e.g. 0x00000042 = "0.42" */ DWORD dwFileVersionMS; /* e.g. 0x00030075 = "3.75" */ DWORD dwFileVersionLS; /* e.g. 0x00000031 = "0.31" */ DWORD dwProductVersionMS; /* e.g. 0x00030010 = "3.10" */ DWORD dwProductVersionLS; /* e.g. 0x00000031 = "0.31" */ DWORD dwFileFlagsMask; /* = 0x3F for version "0.42" */ DWORD dwFileFlags; /* e.g. VFF_DEBUG | VFF_PRERELEASE */ DWORD dwFileOS; /* e.g. VOS_DOS_WINDOWS16 */ DWORD dwFileType; /* e.g. VFT_DRIVER */ DWORD dwFileSubtype; /* e.g. VFT2_DRV_KEYBOARD */ DWORD dwFileDateMS; /* e.g. 0 */ DWORD dwFileDateLS; /* e.g. 0 */ } VS_FIXEDFILEINFO;
dwFileVersionMSはメージャーとマイナーの値を1つのDWORD型へ格納しています。
上位WORDがメジャーバージョン、下位WORDがマイナーバージョンです。
バージョン以外の情報も取得する
TCHAR fileName[ MAX_PATH + 1 ]; DWORD size; BYTE* pVersion; VS_FIXEDFILEINFO* pFileInfo; UINT queryLen; CString fileVersion; CString copyright; CString subBlock; WORD* pLangCode; TCHAR* pStrInfo; ::GetModuleFileName( NULL, fileName, sizeof( fileName ) ); size = ::GetFileVersionInfoSize( fileName, NULL ); pVersion = new BYTE[ size ]; if( ::GetFileVersionInfo( fileName, NULL, size, pVersion ) ) { ::VerQueryValue( pVersion, _T( "\\" ), (void**)&pFileInfo, &queryLen ); fileVersion.Format( _T( "%d.%d.%d.%d" ), HIWORD( pFileInfo->dwFileVersionMS ), LOWORD( pFileInfo->dwFileVersionMS ), HIWORD( pFileInfo->dwFileVersionLS ), LOWORD( pFileInfo->dwFileVersionLS ) ); ::VerQueryValue( pVersion, _T( "\\VarFileInfo\\Translation" ), (void**)&pLangCode, &queryLen ); subBlock.Format( _T( "\\StringFileInfo\\%04X%04X\\LegalCopyright" ), pLangCode[ 0 ], pLangCode[ 1 ] ); ::VerQueryValue( pVersion, (LPTSTR)(LPCTSTR)subBlock, (void**)&pStrInfo, &queryLen ); if( 0 < queryLen ) copyright = pStrInfo; else copyright = _T( "" ); } delete[] pVersion;
バージョン情報リソースを取得 (1~17行目)
ファイルバージョンを取得したのと同じようにバージョン情報のリソースを取得します。
言語識別子とコードページ識別子を取得 (25行目)
VerQueryValue関数の第2引数(取得対象を表す文字)に「\VarFileInfo\Translation」を指定すると言語識別子とコードページ識別子を取得できます。
取得した値の最初のWORDが言語識別子、次のWORDがコードページ識別子となります。
取得対象を表す文字を作成 (27行目)
VerQueryValue関数の第2引数に渡す文字を
「\StringFileInfo\[言語識別子][コードページ識別子]\[定義済みの文字列]」
のように作成します。言語識別子とコードページ識別子はそれぞれ16進表記になります。
定義済み文字列の部分を「LegalCopyright」にすると著作権表記の文字列を取得できます。
定義済み文字列に指定できるものは以下の通りです
- Comments
- InternalName
- ProductName
- CompanyName
- LegalCopyright
- ProductVersion
- FileDescription
- LegalTrademarks
- PrivateBuild
- FileVersion
- OriginalFilename
- SpecialBuild
取得対象の情報を取得 (28~32行目)
上記で作成した文字をVerQueryValue関数の第2引数に指定すると文字列として情報を取得する事ができます。
コメントをお書きください