バージョン情報(バージョンリソース)を取得する

version.gif
EXEファイルやDLLファイルなどに含まれているバージョンリソースから情報を取り出すにはGetFileVersionInfoSize、GetFileVersionInfo、VerQueryValueの3つを利用する。

ファイルによってはバージョン情報リソースが複数の言語分だけ用意されていたり、ひとつもなかったりすることもある。ここではGetThreadLocaleで得られるロケールのリソースから取得を試みて、ダメならファイルにあるリソースから順番に取得した。


#include "DnpFileVersion.h"

void	Test()
{
	CDnpFileVersion	ver;
	CAtlString	str;

	ver.Load(_T("c:\\windows\\system32\\acw.exe"));
	ver.GetProductVersion(str);
	ver.Unload();

	::MessageBox(NULL,str,_T(""),MB_OK);
}


■「DnpFileVersion.h」の内容
#pragma	once


#include "atlstr.h"
#pragma	comment(lib,"Version.lib")


///
///\brief
///		バージョン情報リソース取得クラス
///
///■使用例
/**	\code
	bool	Test()
	{
		CAtlString		strData;
		CDnpFileVersion	cInfo;

		cInfo.Load("C:\\WINDOWS\\system32\\cmd.exe");
		cInfo.GetValue("FileDescription",strData);

		cInfo.GetComments(strData);
		cInfo.GetInternalName(strData);
		cInfo.GetProductName(strData);
		cInfo.GetCompanyName(strData);
		cInfo.GetLegalCopyright(strData);
		cInfo.GetProductVersion(strData);
		cInfo.GetFileDescription(strData);
		cInfo.GetLegalTrademarks(strData);
		cInfo.GetPrivateBuild(strData);
		cInfo.GetFileVersion(strData);
		cInfo.GetOriginalFilename(strData);
		cInfo.GetSpecialBuild(strData);

		return	true;
	}
	\endcode
*///
///
class	CDnpFileVersion
{
protected:

	///
	///\brief
	///		LCIDを展開するための構造体
	///
	struct LANGANDCODEPAGE
	{
	  WORD wLanguage;
	  WORD wCodePage;
	};


	BYTE*				_pVersionInfo;			//!< 保持しているバージョンリソース
	LANGANDCODEPAGE*	_pTranslation;			//!< コードページ情報配列
	UINT				_nTranslationLen;		//!< コードページ情報配列サイズ(要素数)
	UINT				_nTranslationDefault;	//!< デフォルトで用いるコードページ情報配列へのインデックス



public:
	CDnpFileVersion()
	{
		_pVersionInfo = NULL;
		_pTranslation = NULL;
		_nTranslationLen = 0;
		_nTranslationDefault = 0;
	}

	~CDnpFileVersion()
	{
		Unload();
	}


	///
	///\brief
	///		バージョン情報のロード
	///
	///このクラス内にバージョン情報を保持する
	///
	///\param[in]	pszFile
	///	バージョン情報を取得したファイルへのパス(EXEやDLLなど)
	///
	///\retval	true	成功
	///\retval	false	失敗
	///
	bool	Load(LPCTSTR pszFile)
	{
		BOOL	ret;
		DWORD	dwSize;
		BYTE*	pData;
		BYTE*	pResult;
		UINT	nLen;

		Unload();
		dwSize = ::GetFileVersionInfoSize(pszFile,NULL);
		if(dwSize == 0)
			return	false;

		pData = new BYTE[dwSize];
		if(pData == NULL)
			return	false;

		ret = ::GetFileVersionInfo(pszFile,NULL,dwSize,pData);

		if(ret)
			ret = ::VerQueryValue(pData,_T("\\VarFileInfo\\Translation"),(void**)&pResult,&nLen); 

		if(ret == FALSE)
		{
			delete	pData;
			return	false;
		}


		//デフォルトのコードページがみつかればそれを_nTranslationDefaultに保存しておく
		//
		///\todo
		///	//■■デフォルトLCIDが見つからなかったら、ニュートラル言語などほかのを取得しておくべき
		{
			UINT	i;
			LANGANDCODEPAGE*	pLcid;
			LCID	nCurr;

			pLcid = (LANGANDCODEPAGE*)pResult;
			nCurr = ::GetThreadLocale();
			for(i = 0; i < nLen / sizeof(LANGANDCODEPAGE); i++)
			{
				if(pLcid[i].wLanguage != nCurr)
					continue;

				_nTranslationDefault = i;
			}

		}

		_pVersionInfo = pData;
		_pTranslation = (LANGANDCODEPAGE*)pResult;
		_nTranslationLen = nLen / sizeof(LANGANDCODEPAGE);

		return	true;
	}



	///
	///\brief
	///		保持している情報の破棄
	///
	void	Unload(void)
	{
		if(_pVersionInfo)
			delete	_pVersionInfo;
		_pVersionInfo = NULL;
		_pTranslation = NULL;
		_nTranslationLen = 0;
		_nTranslationDefault = 0;
	}


	///
	///\brief
	///		バージョンリソースの項目を取得する
	///
	///\attention
	///	複数のバージョンリソースがあった場合、デフォルトロケールを確認後、
	///最初に見つかったリソースから文字列を返す
	///
	///\param[in]	pszBlockName
	///	取得したいバージョンリソースの名前
	///
	///\param[out]	strValue
	///	取得した文字列
	///
	///\retval	true	取得成功
	///\retval	false	失敗
	///
	bool	GetValue(LPCTSTR pszBlockName,CAtlString& strValue)
	{
		UINT		i;
		BOOL		ret;
		UINT		nLen;
		BYTE*		pData;
		CAtlString	strPath;

		strValue = _T("");

		if(_pVersionInfo == NULL || _pTranslation == NULL || _nTranslationLen == 0)
			return	false;

		//最初にデフォルトロケールで探しておく(_nTranslationDefault==0ならどのみちforで最初に検索されるから問題なし)
		if(_nTranslationDefault)
		{
			i = _nTranslationDefault;
			strPath.Format(_T("\\StringFileInfo\\%04x%04x\\%s"),_pTranslation[i].wLanguage,_pTranslation[i].wCodePage,pszBlockName);
			ret = ::VerQueryValue(_pVersionInfo,strPath.GetBuffer(0),(void**)&pData,&nLen);
			if(ret)
			{
				strValue = (TCHAR*)pData;
				return	true;
			}
		}

		for(i = 0; i < _nTranslationLen; i++)
		{
			strPath.Format(_T("\\StringFileInfo\\%04x%04x\\%s"),_pTranslation[i].wLanguage,_pTranslation[i].wCodePage,pszBlockName);
			ret = ::VerQueryValue(_pVersionInfo,strPath.GetBuffer(0),(void**)&pData,&nLen);
			if(ret == FALSE)
				continue;

			strValue = (TCHAR*)pData;
			return	true;
		}

		return	false;
	}


	///
	///\brief
	///		バージョン情報の「Comments」を取得する
	///
	///\attention
	///	複数のバージョンリソースがあった場合、デフォルトロケールを確認後、
	///最初に見つかったリソースから文字列を返す
	///
	///\param[out]	strValue
	///		取得した文字列
	///
	///\retval	true	取得成功
	///\retval	false	失敗
	///
	bool	GetComments(CAtlString& strValue)
	{
		return	GetValue(_T("Comments"),strValue);
	}



	///
	///\brief
	///		バージョン情報の「InternalName」を取得する
	///
	///\attention
	///	複数のバージョンリソースがあった場合、デフォルトロケールを確認後、
	///最初に見つかったリソースから文字列を返す
	///
	///\param[out]	strValue
	///		取得した文字列
	///
	///\retval	true	取得成功
	///\retval	false	失敗
	///
	bool	GetInternalName(CAtlString& strValue)
	{
		return	GetValue(_T("InternalName"),strValue);
	}



	///
	///\brief
	///		バージョン情報の「ProductName」を取得する
	///
	///\attention
	///	複数のバージョンリソースがあった場合、デフォルトロケールを確認後、
	///最初に見つかったリソースから文字列を返す
	///
	///\param[out]	strValue
	///		取得した文字列
	///
	///\retval	true	取得成功
	///\retval	false	失敗
	///
	bool	GetProductName(CAtlString& strValue)
	{
		return	GetValue(_T("ProductName"),strValue);
	}



	///
	///\brief
	///		バージョン情報の「CompanyName」を取得する
	///
	///\attention
	///	複数のバージョンリソースがあった場合、デフォルトロケールを確認後、
	///最初に見つかったリソースから文字列を返す
	///
	///\param[out]	strValue
	///		取得した文字列
	///
	///\retval	true	取得成功
	///\retval	false	失敗
	///
	bool	GetCompanyName(CAtlString& strValue)
	{
		return	GetValue(_T("CompanyName"),strValue);
	}



	///
	///\brief
	///		バージョン情報の「LegalCopyright」を取得する
	///
	///\attention
	///	複数のバージョンリソースがあった場合、デフォルトロケールを確認後、
	///最初に見つかったリソースから文字列を返す
	///
	///\param[out]	strValue
	///		取得した文字列
	///
	///\retval	true	取得成功
	///\retval	false	失敗
	///
	bool	GetLegalCopyright(CAtlString& strValue)
	{
		return	GetValue(_T("LegalCopyright"),strValue);
	}



	///
	///\brief
	///		バージョン情報の「ProductVersion」を取得する
	///
	///\attention
	///	複数のバージョンリソースがあった場合、デフォルトロケールを確認後、
	///最初に見つかったリソースから文字列を返す
	///
	///\param[out]	strValue
	///		取得した文字列
	///
	///\retval	true	取得成功
	///\retval	false	失敗
	///
	bool	GetProductVersion(CAtlString& strValue)
	{
		return	GetValue(_T("ProductVersion"),strValue);
	}



	///
	///\brief
	///		バージョン情報の「FileDescription」を取得する
	///
	///\attention
	///	複数のバージョンリソースがあった場合、デフォルトロケールを確認後、
	///最初に見つかったリソースから文字列を返す
	///
	///\param[out]	strValue
	///		取得した文字列
	///
	///\retval	true	取得成功
	///\retval	false	失敗
	///
	bool	GetFileDescription(CAtlString& strValue)
	{
		return	GetValue(_T("FileDescription"),strValue);
	}



	///
	///\brief
	///		バージョン情報の「LegalTrademarks」を取得する
	///
	///\attention
	///	複数のバージョンリソースがあった場合、デフォルトロケールを確認後、
	///最初に見つかったリソースから文字列を返す
	///
	///\param[out]	strValue
	///		取得した文字列
	///
	///\retval	true	取得成功
	///\retval	false	失敗
	///
	bool	GetLegalTrademarks(CAtlString& strValue)
	{
		return	GetValue(_T("LegalTrademarks"),strValue);
	}



	///
	///\brief
	///		バージョン情報の「PrivateBuild」を取得する
	///
	///\attention
	///	複数のバージョンリソースがあった場合、デフォルトロケールを確認後、
	///最初に見つかったリソースから文字列を返す
	///
	///\param[out]	strValue
	///		取得した文字列
	///
	///\retval	true	取得成功
	///\retval	false	失敗
	///
	bool	GetPrivateBuild(CAtlString& strValue)
	{
		return	GetValue(_T("PrivateBuild"),strValue);
	}



	///
	///\brief
	///		バージョン情報の「FileVersion」を取得する
	///
	///\attention
	///	複数のバージョンリソースがあった場合、デフォルトロケールを確認後、
	///最初に見つかったリソースから文字列を返す
	///
	///\param[out]	strValue
	///		取得した文字列
	///
	///\retval	true	取得成功
	///\retval	false	失敗
	///
	bool	GetFileVersion(CAtlString& strValue)
	{
		return	GetValue(_T("FileVersion"),strValue);
	}



	///
	///\brief
	///		バージョン情報の「OriginalFilename」を取得する
	///
	///\attention
	///	複数のバージョンリソースがあった場合、デフォルトロケールを確認後、
	///最初に見つかったリソースから文字列を返す
	///
	///\param[out]	strValue
	///		取得した文字列
	///
	///\retval	true	取得成功
	///\retval	false	失敗
	///
	bool	GetOriginalFilename(CAtlString& strValue)
	{
		return	GetValue(_T("OriginalFilename"),strValue);
	}



	///
	///\brief
	///		バージョン情報の「SpecialBuild」を取得する
	///
	///\attention
	///	複数のバージョンリソースがあった場合、デフォルトロケールを確認後、
	///最初に見つかったリソースから文字列を返す
	///
	///\param[out]	strValue
	///		取得した文字列
	///
	///\retval	true	取得成功
	///\retval	false	失敗
	///
	bool	GetSpecialBuild(CAtlString& strValue)
	{
		return	GetValue(_T("SpecialBuild"),strValue);
	}
};

プロジェクトファイルをダウンロード


カテゴリー「ファイル・フォルダ」 のエントリー