获取EXE或者DLL的版本信息

2017年第一篇博客,分享一个获取exe或者dll版本信息的成熟类:

头文件如下:

// ------------------------------------------------------------------------
// 	Copyright   : Copyright(c) 2014-2016 All rights reserved.
// 	FileName    : FileVersion.h
// 	Author		: Kandy
// 	Created		: 2016/8/10 15:48:22
// 	Revision	: $Revision: 1.0 $
// 	Memo		: 
// 	Summary		: 获取EXE/DLL版本信息
// ------------------------------------------------------------------------
#ifndef __BASE_FILE_VERSION_H__
#define __BASE_FILE_VERSION_H__
#include 
#include 

namespace version
{
	// 语言与代码页
	struct LANGANDCODEPAGE
	{
		WORD wLanguage;
		WORD wCodePage;
	};

	//class CLangAndCodePage 
	class CLangAndCodePage : public LANGANDCODEPAGE
	{
	public:
		CLangAndCodePage()
		{
			wLanguage = 0;
			wCodePage = 0;
		}
		CLangAndCodePage(const LANGANDCODEPAGE& wLangAndCodePageSrc)
		{
			wLanguage = wLangAndCodePageSrc.wLanguage;
			wCodePage = wLangAndCodePageSrc.wCodePage;
		}
		CLangAndCodePage(WORD wLanguageSrc, WORD wCodePageSrc)
		{
			wLanguage = wLanguageSrc;
			wCodePage = wCodePageSrc;
		}
	};

	//class CFileVersionInfo 
	class CFileVersionInfo
	{
	public:
		CFileVersionInfo();
		CFileVersionInfo(const wchar_t* szFileName);
		CFileVersionInfo(const wchar_t* szFileName, CLangAndCodePage LangAndCodePage);
		virtual ~CFileVersionInfo();

		std::wstring GetComments();
		std::wstring GetCompanyName();
		std::wstring GetFileDescription();
		std::wstring GetFileVersion();
		std::wstring GetInternalName();
		std::wstring GetLegalCopyright();
		std::wstring GetLegalTrademarks();
		std::wstring GetOriginalTrademarks();
		std::wstring GetPrivateBuild();
		std::wstring GetProductName();
		std::wstring GetProductVersion();
		std::wstring GetSpecialBuild();

		HRESULT Load(const wchar_t* szFileName);
		HRESULT Load(const wchar_t* szFileName, CLangAndCodePage LangAndCodePage);	

	protected:
		UINT GetBuildNumber();
		void GetFileVersionArray(int v[4]);	
		//
		static HRESULT EnumLangAndCodePages(const wchar_t* szFileName, std::vector& LangAndCodePages);
		static std::wstring GetCertificateName(std::wstring filePath);

		// 文件版本信息块
		static LPVOID _AllocFileVersionInfoBlock(const wchar_t* szFileName);
		static void _FreeFileVersionInfoBlock(LPVOID lpBlock);

		static HRESULT _EnumLangAndCodePages(const LPVOID lpBlock, std::vector& LangAndCodePages);

		// szName = "Comments" or "CompanyName" or "FileDescription" or "FileVersion" or
		//          "InternalName" or "LegalCopyright" or "LegalTrademarks" or "OriginalFilename" or
		//          "PrivateBuild" or "ProductName" or "ProductVersion" or "SpecialBuild"
		static HRESULT _GetStringFileInfo(const LPVOID lpBlock, 
			CLangAndCodePage LangAndCodePage, 
			const wchar_t* szName, 
			std::wstring& strValue);

	protected:
		std::wstring m_strFileName;

		std::wstring m_strComments;
		std::wstring m_strCompanyName;
		std::wstring m_strFileDescription;
		std::wstring m_strFileVersion;
		std::wstring m_strInternalName;
		std::wstring m_strLegalCopyright;
		std::wstring m_strLegalTrademarks;
		std::wstring m_strOriginalFilename;
		std::wstring m_strPrivateBuild;
		std::wstring m_strProductName;
		std::wstring m_strProductVersion;
		std::wstring m_strSpecialBuild;
	};
}

#endif//__BASE_FILE_VERSION_H__

实现文件如下:

#include "FileVersion.h"
#include 
#include 
#include 
#pragma comment(lib, "Version.lib")
#pragma comment(lib, "crypt32.lib")
#pragma warning(disable: 4996)

namespace version
{
	CFileVersionInfo::CFileVersionInfo()
	{
	}
	//
	CFileVersionInfo::CFileVersionInfo(const wchar_t* szFileName)
	{
		HRESULT hr = S_OK;

		hr = this->Load(szFileName);
		if (FAILED(hr))
		{
			NULL;
		}
	}
	//
	CFileVersionInfo::CFileVersionInfo(const wchar_t* szFileName, CLangAndCodePage LangAndCodePage)
	{
		HRESULT hr = S_OK;

		hr = this->Load(szFileName, LangAndCodePage);
		if (FAILED(hr))
		{
			NULL;
		}
	}
	//
	CFileVersionInfo::~CFileVersionInfo()
	{
	}
	std::wstring CFileVersionInfo::GetComments()
	{
		return m_strComments;
	}
	std::wstring CFileVersionInfo::GetCompanyName()
	{
		return m_strCompanyName;
	}
	std::wstring CFileVersionInfo::GetFileDescription()
	{
		return m_strFileDescription;
	}
	std::wstring CFileVersionInfo::GetFileVersion()
	{
		if (m_strFileVersion.find(L',') != m_strFileVersion.npos)
		{
			int ver[4];
			GetFileVersionArray(ver);
			wchar_t buf[256];
			swprintf(buf, 256, L"%d.%d.%d.%d", ver[0], ver[1], ver[2], ver[3]);
			return std::wstring(buf);
		}
		return m_strFileVersion;
	}
	std::wstring CFileVersionInfo::GetInternalName()
	{
		return m_strInternalName;
	}
	std::wstring CFileVersionInfo::GetLegalCopyright()
	{
		return m_strLegalCopyright;
	}
	std::wstring CFileVersionInfo::GetLegalTrademarks()
	{
		return m_strLegalTrademarks;
	}
	std::wstring CFileVersionInfo::GetOriginalTrademarks()
	{
		return m_strOriginalFilename;
	}
	std::wstring CFileVersionInfo::GetPrivateBuild()
	{
		return m_strPrivateBuild;
	}
	std::wstring CFileVersionInfo::GetProductName()
	{
		return m_strProductName;
	}
	std::wstring CFileVersionInfo::GetProductVersion()
	{
		return m_strProductVersion;
	}
	std::wstring CFileVersionInfo::GetSpecialBuild()
	{
		return m_strSpecialBuild;
	}
	UINT CFileVersionInfo::GetBuildNumber()
	{
		//找不到资源文件,或者其他问题会返回0
		UINT nBuildNum = 0;
		std::wstring s = m_strFileVersion;
		size_t nPos = s.rfind(L'.');
		if (nPos > 1)
		{
			s = s.substr(nPos + 1);
			nBuildNum = _wtoi(s.c_str());
		}
		return nBuildNum;
	}
	void CFileVersionInfo::GetFileVersionArray(int v[4])
	{
		const wchar_t *p = m_strFileVersion.c_str();
		if (m_strFileVersion.find(L',') != m_strFileVersion.npos)
			swscanf(p, L"%d,%d,%d,%d", &v[0], &v[1], &v[2], &v[3]);
		else
			swscanf(p, L"%d.%d.%d.%d", &v[0], &v[1], &v[2], &v[3]);
	}
	//
	HRESULT CFileVersionInfo::Load(const wchar_t* szFileName, CLangAndCodePage LangAndCodePage)
	{
		wchar_t lpPath[MAX_PATH] = { 0 };

		if (szFileName == NULL)
		{
			::GetModuleFileNameW(NULL, lpPath, MAX_PATH);
			szFileName = lpPath;
		}

		HRESULT hr = S_OK;

		LPVOID lpBlock = _AllocFileVersionInfoBlock(szFileName);
		if (lpBlock == NULL)
		{
			return E_OUTOFMEMORY;
		}

		hr = _GetStringFileInfo(lpBlock, LangAndCodePage, _T("Comments"), m_strComments);
		hr = _GetStringFileInfo(lpBlock, LangAndCodePage, _T("CompanyName"), m_strCompanyName);
		hr = _GetStringFileInfo(lpBlock, LangAndCodePage, _T("FileDescription"), m_strFileDescription);
		hr = _GetStringFileInfo(lpBlock, LangAndCodePage, _T("FileVersion"), m_strFileVersion);
		hr = _GetStringFileInfo(lpBlock, LangAndCodePage, _T("InternalName"), m_strInternalName);
		hr = _GetStringFileInfo(lpBlock, LangAndCodePage, _T("LegalCopyright"), m_strLegalCopyright);
		hr = _GetStringFileInfo(lpBlock, LangAndCodePage, _T("LegalTrademarks"), m_strLegalTrademarks);
		hr = _GetStringFileInfo(lpBlock, LangAndCodePage, _T("OriginalFilename"), m_strOriginalFilename);
		hr = _GetStringFileInfo(lpBlock, LangAndCodePage, _T("PrivateBuild"), m_strPrivateBuild);
		hr = _GetStringFileInfo(lpBlock, LangAndCodePage, _T("ProductName"), m_strProductName);
		hr = _GetStringFileInfo(lpBlock, LangAndCodePage, _T("ProductVersion"), m_strProductVersion);
		hr = _GetStringFileInfo(lpBlock, LangAndCodePage, _T("SpecialBuild"), m_strSpecialBuild);

		_FreeFileVersionInfoBlock(lpBlock);

		return S_OK;
	}
	//
	HRESULT CFileVersionInfo::Load(const wchar_t* szFileName)
	{
		wchar_t lpPath[MAX_PATH] = { 0 };

		if (szFileName == NULL)
		{
			::GetModuleFileNameW(NULL, lpPath, MAX_PATH);
			szFileName = lpPath;
		}

		HRESULT hr = S_OK;

		std::vector LangAndCodePages;
		hr = EnumLangAndCodePages(szFileName, LangAndCodePages);
		if (FAILED(hr))
		{
			return hr;
		}

		return this->Load(szFileName, LangAndCodePages[0]);
	}
	//
	HRESULT CFileVersionInfo::EnumLangAndCodePages(const wchar_t* szFileName, std::vector& LangAndCodePages)
	{
		if (szFileName == NULL)
		{
			return E_FAIL;
		}

		HRESULT hr = S_OK;

		LPVOID lpBlock = _AllocFileVersionInfoBlock(szFileName);
		if (lpBlock == NULL)
		{
			return E_OUTOFMEMORY;
		}

		hr = _EnumLangAndCodePages(lpBlock, LangAndCodePages);

		_FreeFileVersionInfoBlock(lpBlock);

		return hr;
	}
	//
	std::wstring CFileVersionInfo::GetCertificateName(std::wstring filePath)
	{
		std::wstring cfeName;
		HCERTSTORE hStore = NULL;
		HCRYPTMSG hMsg = NULL;
		PCCERT_CONTEXT pCertContext = NULL;
		PCMSG_SIGNER_INFO pSignerInfo = NULL;
		DWORD dwSignerInfo;
		CERT_INFO CertInfo;
		wchar_t szName[1024] = { 0 };

		// Get message handle and store handle from the signed file.
		BOOL fResult = CryptQueryObject(CERT_QUERY_OBJECT_FILE, filePath.c_str(), CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
			CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL, NULL, &hStore, &hMsg, NULL);
		if (!fResult)
		{
			goto __GetCertificateNameEnd;
		}
		// Get signer information size.
		fResult = CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &dwSignerInfo);
		if (!fResult)
		{
			goto __GetCertificateNameEnd;
		}
		// Allocate memory for signer information.
		pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
		if (!pSignerInfo)
		{
			goto __GetCertificateNameEnd;
		}
		// Get Signer Information.
		fResult = CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, (PVOID)pSignerInfo, &dwSignerInfo);
		if (!fResult)
		{
			goto __GetCertificateNameEnd;
		}

		CertInfo.Issuer = pSignerInfo->Issuer;
		CertInfo.SerialNumber = pSignerInfo->SerialNumber;
		pCertContext = CertFindCertificateInStore(hStore, (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING), 0,
			CERT_FIND_SUBJECT_CERT, (PVOID)&CertInfo, NULL);
		if (!pCertContext)
		{
			goto __GetCertificateNameEnd;
		}

		if (dwSignerInfo = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, NULL, NULL, NULL, 0))
		{
			if (CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, NULL, NULL, szName, dwSignerInfo))
			{
				cfeName = szName;
			}
		}

__GetCertificateNameEnd:
		if (pSignerInfo != NULL) LocalFree(pSignerInfo);
		if (pCertContext != NULL) CertFreeCertificateContext(pCertContext);
		if (hStore != NULL) CertCloseStore(hStore, 0);
		if (hMsg != NULL) CryptMsgClose(hMsg);

		return cfeName;
	}

	// 文件版本信息块
	LPVOID CFileVersionInfo::_AllocFileVersionInfoBlock(const wchar_t* szFileName)
	{
		if (szFileName == NULL)
		{
			return NULL;
		}

		DWORD dwHandle = 0;
		DWORD dwBlockSize = ::GetFileVersionInfoSize(szFileName, &dwHandle);
		if (dwBlockSize <= 0)
		{
			return NULL;
		}

		LPVOID lpBlock = new char[dwBlockSize];
		if (lpBlock == NULL)
		{
			return NULL;
		}

		BOOL br = ::GetFileVersionInfoW(szFileName, dwHandle, dwBlockSize, lpBlock);
		if (br == FALSE)
		{
			delete[] lpBlock;
			return NULL;
		}

		return lpBlock;
	}
	void CFileVersionInfo::_FreeFileVersionInfoBlock(LPVOID lpBlock)
	{
		delete[] lpBlock;
	}

	HRESULT CFileVersionInfo::_EnumLangAndCodePages(const LPVOID lpBlock, std::vector& LangAndCodePages)
	{
		if (lpBlock == NULL)
		{
			return E_FAIL;
		}

		// 清除
		LangAndCodePages.clear();

		wchar_t strSubBlock[] = L"\\VarFileInfo\\Translation";
		LPVOID lpBuffer = NULL;
		UINT uLen = 0;

		BOOL br = ::VerQueryValue(lpBlock, strSubBlock, (LPVOID*)&lpBuffer, &uLen);
		if (br == 0)
		{
			return E_FAIL;
		}

		for (int i = 0; i < (int)(uLen / sizeof(struct LANGANDCODEPAGE)); i++)
		{
			LANGANDCODEPAGE* pLangAndCodePage = (LANGANDCODEPAGE*)lpBuffer;

			LangAndCodePages.push_back(pLangAndCodePage[i]);
		}

		return S_OK;
	}
	// szName = "Comments" or "CompanyName" or "FileDescription" or "FileVersion" or
	//          "InternalName" or "LegalCopyright" or "LegalTrademarks" or "OriginalFilename" or
	//          "PrivateBuild" or "ProductName" or "ProductVersion" or "SpecialBuild"
	HRESULT CFileVersionInfo::_GetStringFileInfo(const LPVOID lpBlock, CLangAndCodePage LangAndCodePage, const wchar_t* szName, std::wstring& strValue)
	{
		if (lpBlock == NULL)
		{
			return E_FAIL;
		}

		// 清除
		strValue = _T("");

		wchar_t strSubBlock[256];
		swprintf(strSubBlock, 256, L"\\StringFileInfo\\%04x%04x\\%s", LangAndCodePage.wLanguage, LangAndCodePage.wCodePage, szName);
		LPVOID lpBuffer = NULL;
		UINT uLen = 0;

		BOOL br = ::VerQueryValueW(lpBlock, strSubBlock, &lpBuffer, &uLen);
		if (br == 0)
		{
			return E_FAIL;
		}

		strValue = (const wchar_t*)lpBuffer;

		return S_OK;
	}
}

你可能感兴趣的:(Windows,程序设计)