読者です 読者をやめる 読者になる 読者になる

自分自身のリソースからアプリケーション名とバージョン番号を取得する

C++Builderの[プロジェクト|オプション|バージョン番号]で設定したバージョン番号を取得するには、GetFileVersionInfoとVerQueryValueを使用してアプリケーションの情報を取得する。VerQueryValueで戻ってくるサイズは文字数。

UnicodeString GetApplicationNameAndVersion()
{
  // 自分自身のフルパス
  const TCHAR* ExeName = Application->ExeName.t_str();

  // リソース領域のサイズを取得
  DWORD Size = GetFileVersionInfoSize(ExeName, NULL);

  // リソース領域を取得
  BYTE *pVersionInfo = new BYTE[Size];
  GetFileVersionInfo(ExeName, NULL, Size, pVersionInfo);

  // アプリケーション名を取得
  VOID* pProductName;  // アプリケーション名へのポインタ
  UINT ProductNameLength;  // アプリケーション名の文字列長さ
  VerQueryValue(pVersionInfo, _T("\\StringFileInfo\\041103A4\\ProductName"), 
    &pProductName, &ProductNameLength);
  UnicodeString strProductName((TCHAR*)pProductName, ProductNameLength);

  // バージョン番号を取得
  VOID* pVersion;
  UINT VersionLength;
  VerQueryValue(pVersionInfo, _T("\\StringFileInfo\\041103A4\\ProductVersion"),
    &pVersion, &VersionLength);
  UnicodeString strVersion((TCHAR*)pVersion, VersionLength);

  UnicodeString AppVersion;
  // 本当は、VerQueryValueで戻ってきた文字列長を考慮して、ヌルターミネーターの処理をすべきかも。
  AppVersion.printf(L"%s Version %s", pProductName, pVersion);

  // 後始末
  delete pVersionInfo;

  return AppVersion;
}

マジックナンバー"041103A4"の意味は、"0411"は日本語のロカールIDで"03A4"はコードページ。C++BuilderはSHIFT-JIS(0x03a4=932)となっている。VisualC++の例だとUTF-16LE(0x04b0=1200)の場合もある。
もしかしたら、言語ロカールIDとコードページをマジックナンバーで決め打ちするのではなく、リソース領域からLANGANDCODEPAGEでロカールIDを列挙するのが正式な作法かもしれない。