C++でバージョン情報を取得する

Visual Studioなどで開発していると、バージョン番号はリソースで値を管理することになります。

リソースで設定すると、内容がEXEファイルのプロパティの詳細タブでも確認できるようになるので便利ですね。

 

このような情報は1か所で管理するべきなので、バージョン情報画面などを出した場合リソースから値を取得する必要があります。

C#の場合はこちら↓

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がマイナーバージョンです。

バージョン以外の情報も取得する

タイトルや著作権表記を取得したい場合もVerQueryValue関数を使ってリソースから取得する事ができます。

 

以下の例では、ファイルバージョンに加えて著作権表記を取得しています。

    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引数に指定すると文字列として情報を取得する事ができます。