2024/06/03 電子書籍「電子書籍出版・技術文書作成を劇的に加速!秀丸エディタ + Markdown + Pandocの驚異」を出版

ファイルのバージョン情報とAboutダイアログ

C++Builder

Windowsのアプリケーションを作成する時に、ファイルのバージョン情報を設定されているでしょうか?また、その情報をアプリケーションで使用しているでしょうか?

この記事では、ファイルのバージョン情報の概要と、その情報をAboutダイアログで活用する方法について解説します。

ファイルのバージョン情報

Windowsのファイルのバージョン情報は、ファイルに埋め込まれているメタデータの一部で、特に実行可能ファイル(.exe)、動的リンクライブラリ(.dll)、ドライバなどに使われています。この情報は、ファイルのバージョン管理やソフトウェアの更新、トラブルシューティングなどに役立ちます。

バージョン情報の主な項目

主な項目説明
製品バージョン(Product Version)ファイルが含まれる製品全体のバージョン番号を示します。例えば、特定のバージョンのアプリケーションやソフトウェアスイートに対応するバージョン番号です。
著作権(Copyright)ファイルの著作権情報が記載されています。通常、会社名や年号が含まれます。
会社名(Company Name)ファイルを作成した企業や組織の名称が表示されます。
製品名(Product Name)ファイルが含まれる製品の正式な名前です。
内部名(Internal Name)ソフトウェア開発者が使用する内部的な名前が記載されていることがあります。
オリジナルファイル名(Original Filename)元のファイル名が表示されます。たとえば、変更やリネームされても、この項目には元の名前が保持されます。
説明(File Description)ファイルの簡単な説明が記載されています。通常、実行可能ファイルが何をするかについての短い説明がここに含まれます。
バージョン情報の主な項目

バージョン情報の確認方法

ファイルのバージョン情報は、エクスプローラーを使用して次の手順で確認できます。

  1. 確認したいファイルを右クリックし、「プロパティ」を選択。
  2. 詳細」タブを開くと、バージョン情報やその他のファイル情報が表示されます。

バージョン情報はエクスプローラーから簡単に確認できるため、アプリケーションを作成する際には、バージョン管理の観点からも正確な情報を設定することをお勧めします。

C++Builderでの、バージョン情報の登録

C++Builderで、初めてのプロジェクト作成 で説明した、「SDIアプリケーション」を元に説明します。

「オプション」ダイアログの表示

メニューの「プロジェクト」→「オプション」から「オプション」ダイアログを表示します。

「バージョン情報」の入力画面の表示

「アプリケーション」→「バージョン情報」を選択し、バージョン情報の入力画面を表示します。

「バージョン情報」の入力

バージョン情報の入力画面から、バージョン情報を入力します。

手順としては、上から

  1. 設定するプラットフォームを選択
    • 「すべての構成」を選択することもできますが、一度「Debug構成」か[Release構成]を入力すると、「すべての構成」で入力した内容が反映されないようですので注意してください。
  2. 「バージョン番号を含める」にチェックを入れます。
  3. 「モジュールのバージョン番号」を設定します。
    • 「モジュールのバージョン番号」は、「ファイルバージョン」に自動的にセットされます。
  4. 「言語」、「ロケール」ですが、「日本語(日本)」を選択すれば良いかと思います。
  5. ファイルのバージョン情報の各項目を入力します。
    • 「製品バージョン」には、「モジュールのバージョン番号」の値は、反映されませんので、手入力する必要があります。

「About」ダイアログに、バージョン情報を表示

「SDIアプリケーション」には、雛形の「About」ダイアログが自動的に生成されます。

この「About」ダイアログは、作成したアプリケーションの情報を表示するのに使用されます。先ほど入力した「バージョン情報」から「製品名」や「バージョン」情報等を取得し、表示する方法をご紹介します。

GetFileVersionInfoでァイルのバージョン情報を取得

ファイルのバージョン情報を取得は、WIN32のAPI の「GetFileVersionInfo」で取得する事ができます。

最初に GetFileVersionInfoSize 関数を呼び出して、ファイルのバージョン情報のサイズ (バイト単位) を取得し、その情報を使用して GetFileVersionInfo 関数を呼び出します。実際のデータ取得は、VerQueryValue関数で行います。VerQueryValue関数でバージョンの各データを取得するには、言語とコード ページ識別子が必要です。

以下は、言語として日本語を指定して、バージョン情報を取得するサンプルコードです。

#define ID_CompanyName			0
#define ID_FileDescription		1
#define ID_FileVersion			2
#define ID_InternalName			3
#define ID_LegalCopyright		4
#define ID_OriginalFilename		5
#define ID_ProductVersion		6
#define ID_ProductName			7
#define ID_Comments				8
#define ID_LegalTrademarks		9
#define ID_PrivateBuild			10
#define ID_SpecialBuild			11


/* =================================================================== */
// リソース(ファイル情報)から、バージョン情報を入手
// static String GetFileInfo(int id)
String GetFileInfo(int id)
{
	String VerNo = "";
	// HANDLE infoHandle;
	DWORD InfoSize, size;
	InfoSize = GetFileVersionInfoSize(Application->ExeName.c_str() , nullptr);
	
	String key = "\\StringFileInfo\\041103a4\\";  // 日本語の場合
	switch(id)
	{
		case ID_CompanyName:
			key += "CompanyName";
			break;
		case ID_FileDescription:
			key += "FileDescription";
			break;
		case ID_FileVersion:
			key += "FileVersion";
			break;
		case ID_InternalName:
			key += "InternalName";
			break;
		case ID_LegalCopyright:
			key += "LegalCopyright";
			break;
		case ID_OriginalFilename:
			key += "OriginalFilename";
			break;
		case ID_ProductName:
			key += "ProductName";
			break;
		case ID_Comments:
			key += "Comments";
			break;

		case ID_LegalTrademarks:
			key += "LegalTrademarks";
			break;

		case ID_PrivateBuild:
			key += "PrivateBuild";
			break;

		case ID_SpecialBuild:
			key += "SpecialBuild";
			break;

		case ID_ProductVersion:
		default:
			key += "ProductVersion";
			break;
	}

	if(InfoSize != 0)
	{
		_TCHAR *infobuf = new _TCHAR[InfoSize + 1];
		_TCHAR *info;

		if( GetFileVersionInfo(Application->ExeName.c_str(), NULL, InfoSize, infobuf))
		{
			// if USA, lang-charset is 040904E4,	932 -> 0x3a4
			// ProductVersion, FileVersion, ProductName
			if( VerQueryValue(infobuf, key.c_str(), (LPVOID *)&info, (PUINT )&size) )
			{
				// ShowMessage(info);
				VerNo = info;
				// AppCaption += (String)" V" + info;
			}
		}
		
		delete[] infobuf;
	}
	return VerNo;
}

以下は、VerQueryValue関数で使用されている言語とコード ページ識別子を取得後、バージョン情報のデータを取得するサンプルコードです。

String GetFileInfo(int id)
{
	String VerNo = "";
	// HANDLE infoHandle;
	DWORD InfoSize, size;
	InfoSize = GetFileVersionInfoSize(Application->ExeName.c_str() , nullptr);

	if(InfoSize != 0)
	{
		_TCHAR *infobuf = new _TCHAR[InfoSize + 1];
		_TCHAR *info;

		if( GetFileVersionInfo(Application->ExeName.c_str(), NULL, InfoSize, infobuf))
		{
			UINT nLen;
			String StrSubBlock	= _T("\\VarFileInfo\\Translation");
			struct LANGANDCODEPAGE {
				WORD wLanguage;
				WORD wCodePage;
			} *lpTranslate;

			// lang-codepageを取得
			if(::VerQueryValue(infobuf, StrSubBlock.c_str(), (LPVOID*)&lpTranslate, &nLen))
			{
				// lang-codepageをフォーマット
				String StrLang	= IntToHex(lpTranslate->wLanguage, 4) + IntToHex(lpTranslate->wCodePage, 4);

				// String key = "\\StringFileInfo\\041103a4\\";
				String key = "\\StringFileInfo\\" + StrLang + "\\";
				switch(id)
				{
					case ID_CompanyName:
						key += "CompanyName";
						break;
					case ID_FileDescription:
						key += "FileDescription";
						break;
					case ID_FileVersion:
						key += "FileVersion";
						break;
					case ID_InternalName:
						key += "InternalName";
						break;
					case ID_LegalCopyright:
						key += "LegalCopyright";
						break;
					case ID_OriginalFilename:
						key += "OriginalFilename";
						break;
					case ID_ProductName:
						key += "ProductName";
						break;
					// 2024/02/24 追加
					case ID_Comments:
						key += "Comments";
						break;

					case ID_LegalTrademarks:
						key += "LegalTrademarks";
						break;

					case ID_PrivateBuild:
						key += "PrivateBuild";
						break;

					case ID_SpecialBuild:
						key += "SpecialBuild";
						break;

					case ID_ProductVersion:
					default:
						key += "ProductVersion";
						break;
				}
				// 情報を取得する
				if( VerQueryValue(infobuf, key.c_str(), (LPVOID *)&info, (PUINT )&size) )
				{
					// ShowMessage(info);
					VerNo = info;
				}
			}
		}
		delete[] infobuf;
	}
	return VerNo;
}

「About」ダイアログ

GetFileInfo関数を使用してバージョン情報を取得し、「About」ダイアログを作成するサンプルです。

  • 使用している、バージョン情報
    • ProductName
    • FileVersion
    • LegalCopyright
    • Comments
  • GetFileInfoの使用例
__fastcall TAboutBox::TAboutBox(TComponent *Owner)
	: TForm(Owner)
{
	Version->Caption		= (String)"     Version " + GetFileInfo(ID_FileVersion);
	ProductName->Caption	= GetFileInfo(ID_ProductName);
	Copyright->Caption		= GetFileInfo(ID_LegalCopyright);
	Comments->Caption		= GetFileInfo(ID_Comments);	// Comments->Caption		= GetFileInfo(ID_FileDescription);
}
  • サンプルの「About」ダイアログの表示
  • サンプルコードのダウンロード
About用sdiapp Project

ファイルのバージョン情報から、「About」ダイアログを作成する「sdiapp」の サンプルプロジェクトです。

「バージョン情報」を書き替えると、「About」ダイアログで表示されるな内容も自動的に更新されて楽ですね。情報の一元管理としても便利です。

「sdiapp.exe」のバージョン情報の確認

エクスプローラーを使用して、「sdiapp.exe」のバージョン情報を確認してみましょう。

ファイルのバージョン情報は、エクスプローラーを使用して次の手順で確認できます。

1.「sdiapp.exe」を選択して右クリックし、「プロパティ」を選択。

2.「詳細」タブを開くと、バージョン情報やその他のファイル情報が表示されます。

C++Builderのバージョン情報の入力画面で入力した内容が表示されていることがわかります。

キー項目と各項目との対応

C++Builderのバージョン情報の入力画面の、キーの項目と以下のIDとの対応を確認してみましょう。

#define ID_CompanyName			0
#define ID_FileDescription		1
#define ID_FileVersion			2
#define ID_InternalName			3
#define ID_LegalCopyright		4
#define ID_OriginalFilename		5
#define ID_ProductVersion		6
#define ID_ProductName			7
#define ID_Comments				8
#define ID_LegalTrademarks		9
#define ID_PrivateBuild			10
#define ID_SpecialBuild			11

以下は、「sdiapp.exe」で、左端のスピードボタンを押すと、各IDに対応するバージョン情報を取得して表示する機能を実装した際の表示結果です。

キー項目とID及びプロパティ情報の対応

以下は、キー項目とID及びエクスプローラーで表示されるプロパティ情報をまとめた表です。

キーIDプロパティ
会社名ID_CompanyNameCompanyName
ファイルバージョンID_FileVersionFileVersionファイルバージョン
内部名ID_InternalNameInternalName
著作権ID_LegalCopyrightLegalCopyright著作権
商標ID_LegalTrademarksLegalTrademarks商標
正式ファイル名ID_OriginalFilenameOriginalFilename元のファイル名
製品バージョンID_ProductVersionProductVersion製品バージョン
コメントID_CommentsComments
ProgramID
説明ID_FileDescriptionFileDescriptionファイルの説明
製品名ID_ProductNameProductName製品名
キー項目とID及びプロパティ情報の対応
タイトルとURLをコピーしました