experiment: GetMouldInfoViaPathName

// Win32Console.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <string>
#include <TlHelp32.h>

#pragma comment(lib, "Version.lib")

BOOL  GetMouldInfoViaPathName(LPCTSTR  lpFilePath, 
							  TCHAR * lpcProcessMouldName, size_t nLenProcessMouldName,
							  TCHAR * lpcProcessFileVersion, size_t nLenProcessFileVersion);

int _tmain(int argc, _TCHAR* argv[])
{
	BOOL bRc = FALSE;
	TCHAR szProcessMouldName[_MAX_PATH];
	TCHAR szProcessFileVersion[_MAX_PATH];

	bRc = GetMouldInfoViaPathName(L"d:\\temp\\ProcExp.exe", 
		szProcessMouldName, _MAX_PATH,
		szProcessFileVersion, _MAX_PATH);
	if(!bRc)
	{
		_tprintf(_T("%s = %d\n"), L"bRc", bRc);
	}

_tmain_END:
	getchar();
	return 0;
}

BOOL  GetMouldInfoViaPathName(LPCTSTR  lpFilePath, 
							  TCHAR * lpcProcessMouldName, size_t nLenProcessMouldName,
							  TCHAR * lpcProcessFileVersion, size_t nLenProcessFileVersion)
{
	BOOL	bRc = FALSE;
	DWORD	dwHandle = 0;
	DWORD	dwSize = 0;
	UINT	dwBytes = 0;
	UINT	cbTranslate = 0;
	HRESULT hr = NULL;
	PBYTE	lpContent = NULL;
	PBYTE	lpVersion = NULL;
	LPVOID  lpBuffer = NULL;
	TCHAR   szSubBlock[_MAX_PATH];

	struct LANGANDCODEPAGE
	{
		WORD wLanguage;
		WORD wCodePage;
	}*lpTranslate;

	if (NULL == lpFilePath)
	{
		goto _GetMouldInfoViaPathName_END;
	}

	dwSize = GetFileVersionInfoSize(lpFilePath, &dwHandle);
	lpContent = (PBYTE)malloc(dwSize);
	GetFileVersionInfo(lpFilePath, NULL, dwSize, lpContent);
	VerQueryValue(lpContent, L"\\VarFileInfo\\Translation",
		(LPVOID*)&lpTranslate, &cbTranslate);

	/// 得文件模块名(原始文件名)
	for(ULONG i=0; i < (cbTranslate / sizeof(struct LANGANDCODEPAGE)); i++)
	{
		bRc = FALSE;
		hr = swprintf(szSubBlock,
			L"\\StringFileInfo\\%04x%04x\\OriginalFilename",
			lpTranslate[i].wLanguage,lpTranslate[i].wCodePage);
		if (FAILED(hr))
		{
			continue;
		}

		VerQueryValue(lpContent, szSubBlock, &lpBuffer, &dwBytes); 
		if(NULL == lpBuffer)
		{
			continue;
		}

		if(_tcslen((LPCTSTR)lpBuffer) < nLenProcessMouldName)
		{
			_tcscpy(lpcProcessMouldName, (LPCTSTR)lpBuffer);
		}

		hr = swprintf(szSubBlock,
			//L"\\StringFileInfo\\%04x%04x\\ProductVersion",
			L"\\StringFileInfo\\%04x%04x\\FileVersion",
			lpTranslate[i].wLanguage,lpTranslate[i].wCodePage);
		if (FAILED(hr))
		{
			continue;
		}

		VerQueryValue(lpContent, szSubBlock, &lpBuffer, &dwBytes); 
		if(NULL == lpBuffer)
		{
			continue;
		}

		if(_tcslen((LPCTSTR)lpBuffer) < nLenProcessFileVersion)
		{
			_tcscpy(lpcProcessFileVersion, (LPCTSTR)lpBuffer);
			bRc = TRUE; ///< 文件模块名称和文件版本全部得到后, 就成功结束
			break;
		}
	}

_GetMouldInfoViaPathName_END:
	if (NULL != lpContent)
	{
		free(lpContent);
		lpContent = NULL;
	}

	return bRc;
}


<2012/4/22>

CodeProject上有个类,  很方便的取文件版本.

http://www.codeproject.com/Articles/1502/CFileVersionInfo-Retrieving-a-File-s-full-Version
CFileVersionInfo - Retrieving a File's full Version Information Resource

但是那个工程是MFC的, 不符合我的应用(pure win32 c++, unicode string only).

我修改成使用std::wstring, 加了一个文件版本比较函数.

// srcFileGetVersionViaFilePathName.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <string>
#include "file/FileVersionInfo.h"

// test file version is 1.80.4145.0
/// 设计版本比较时的各种情况
const TCHAR * g_strFileVerArr[] =
{
	_T("1.80.4145.0"),
	_T("2.1.4145.0"),
	_T("0.1.4145.0"), 
	_T("1.81.4145.0"),
	_T("1.79.4145.0"),
	_T("1.80.4400.0"),
	_T("1.80.5.0"),
	_T("1.80.4145.1"),
	_T("1.80"),
	_T("1.80.4145.0.1"),
	NULL
};

int _tmain(int argc, _TCHAR* argv[])
{
	BOOL bRc = TRUE;
	INT iRc = 0;
	size_t nPos = 0;
	CFileVersionInfo fileInfo;

	bRc = fileInfo.Create(_T("d:\\temp\\QQ.exe"));
	if(bRc)
	{
		fileInfo.ShowFileVersionInfo();
	}
	else
	{
		_tprintf(_T("error on fileInfo.Create\n"));
	}

	while(NULL != *(g_strFileVerArr + nPos))
	{
		iRc = fileInfo.CompareFileVersion((TCHAR *) *(g_strFileVerArr + nPos));
		if(iRc > 0)
		{
			_tprintf(_T("file version %s > %s\n"), fileInfo.GetFileVersion(), *(g_strFileVerArr + nPos));
		}
		else if(0 == iRc)
		{
			_tprintf(_T("file version %s == %s\n"), fileInfo.GetFileVersion(), *(g_strFileVerArr + nPos));
		}
		else if(iRc < 0)
		{
			_tprintf(_T("file version %s < %s\n"), fileInfo.GetFileVersion(), *(g_strFileVerArr + nPos));
		}

		nPos++;
	}

/** run results
File [d:\temp\QQ.exe] information below:
m_strCompanyName = Tencent
m_strFileDescription =
m_strFileVersion = 1.80.4145.0
m_strInternalName =
m_strLegalCopyright = Copyright (c) 2012 Tencent All Rights Reserved
m_strOriginalFileName =
m_strProductName =
m_strProductVersion = 1.80.4145.0
m_strComments =
m_strLegalTrademarks =
m_strPrivateBuild =
file version 1.80.4145.0 == 1.80.4145.0
file version 1.80.4145.0 < 2.1.4145.0
file version 1.80.4145.0 > 0.1.4145.0
file version 1.80.4145.0 < 1.81.4145.0
file version 1.80.4145.0 > 1.79.4145.0
file version 1.80.4145.0 < 1.80.4400.0
file version 1.80.4145.0 > 1.80.5.0
file version 1.80.4145.0 < 1.80.4145.1
file version 1.80.4145.0 > 1.80
file version 1.80.4145.0 == 1.80.4145.0.1
*/
	getchar();
	return 0;
}

/********************************************************************
*
* Copyright (C) 1999-2000 Sven Wiegand
* Copyright (C) 2000-2001 ToolsCenter
* 
* This file is free software; you can redistribute it and/or
* modify, but leave the headers intact and do not remove any 
* copyrights from the source.
*
* If you have further questions, suggestions or bug fixes, visit 
* our homepage
*
*    http://www.ToolsCenter.org
*
********************************************************************/

//////////////////////////////////////////////////////////////////////////
/// @file FileVersionInfo.h
/// @brief modify Sven Wiegand's CFileVersionInfo to no mfc progam version
/// @author LostSpeed
/// @date 2012/4/21
/// @history
/// 2012/4/21 修改CString to std::wstring, add CompareFileVersion
//////////////////////////////////////////////////////////////////////////

#ifndef __FILE_VERSION_INFO_H__
#define __FILE_VERSION_INFO_H__

#include <windows.h>
#include <tchar.h>
#include <string>
#include <winver.h>

#ifndef _UNICODE
#error "only support unicode"
#endif

#ifndef tstring
#ifdef _UNICODE
#define tstring std::wstring
#else
#define tstring std::string
#endif
#endif

#define FILE_VERSION_COMMENTS			_T("Comments")
#define FILE_VERSION_INTERNAL_NAME		_T("InternalName")
#define FILE_VERSION_PRODUCT_NAME		_T("ProductName")
#define FILE_VERSION_COMPANY_NAME		_T("CompanyName")
#define FILE_VERSION_LEGAL_COPYRIGHT	_T("LegalCopyright")
#define FILE_VERSION_PRODUCT_VERSION	_T("ProductVersion")
#define FILE_VERSION_FILE_DESCRIPTION	_T("FileDescription")
#define FILE_VERSION_LEGAL_TRADEMARKS	_T("LegalTrademarks")
#define FILE_VERSION_PRIVATE_BUILD		_T("PrivateBuild")
#define FILE_VERSION_FILE_VERSION		_T("FileVersion")
#define FILE_VERSION_ORIGINAL_FILENAME	_T("OriginalFilename")
#define FILE_VERSION_SPECIAL_BUILD		_T("SpecialBuild")

class CFileVersionInfo
{
// construction/destruction
public:
	CFileVersionInfo();
	virtual ~CFileVersionInfo();

// operations
public:
	BOOL	Create(HMODULE hModule = NULL);
	BOOL	Create(CONST TCHAR * lpcFilePathName);
	VOID	ShowFileVersionInfo();

// attribute operations
public:
	TCHAR * GetFilePathName()	CONST;
	WORD	GetFileVersion(INT iIndex)	CONST;
	WORD	GetProductVersion(INT iIndex)	CONST;
	DWORD	GetFileFlagsMask()	CONST;
	DWORD	GetFileFlags()	CONST;
	DWORD	GetFileOs()	CONST;
	DWORD	GetFileType()	CONST;
	DWORD	GetFileSubtype()	CONST;
	VOID	GetFileDate(FILETIME * ft)	CONST;

	TCHAR * GetCompanyName()	CONST;
	TCHAR * GetFileDescription()	CONST;
	TCHAR * GetFileVersion()	CONST;
	TCHAR * GetInternalName()	CONST;
	TCHAR * GetLegalCopyright()	CONST;
	TCHAR * GetOriginalFileName()	CONST;
	TCHAR * GetProductName()	CONST;
	TCHAR * GetProductVersion()	CONST;
	TCHAR * GetComments()	CONST;
	TCHAR * GetLegalTrademarks()	CONST;
	TCHAR * GetPrivateBuild()	CONST;
	TCHAR * GetSpecialBuild()	CONST;

	/// @fn INT CompareFileVersion(TCHAR * lpcFileVersion)
	/// @brief 用本类中得到的文件版本和给定的文件版本进行比对
	/// @param TCHAR * lpcFileVersion, 需要比较的文件版本串, 例如 _T("1.0.0.1")
	/// @return INT
	/// @retval 0, 相同的版本
	/// @retval 1, 本类中的文件版串 > 给定的文件版本串, 例如 _T("1.0.0.1") > _T("1.0.0.0")
	/// @retval -1, 本类中的文件版串 < 给定的文件版本串, 例如 _T("1.0.0.0") < _T("1.0.0.1")
	INT CompareFileVersion(TCHAR * lpcFileVersion);

// implementation helpers
protected:
	virtual	VOID	Reset();
	BOOL	GetTranslationId(LPVOID lpData, UINT uBlockSize, WORD wLangId, DWORD &dwId, BOOL bPrimaryEnough = FALSE);
	tstring QueryValue(LPVOID lpData, tstring & strSubBlock, CONST TCHAR * lpcSubBlockKeyName, LPVOID lpInfo, UINT unInfoLen);

// attributes
private:
	tstring m_strFilePathName;
	VS_FIXEDFILEINFO m_FileInfo;

	tstring m_strCompanyName;
	tstring m_strFileDescription;
	tstring m_strFileVersion;
	tstring m_strInternalName;
	tstring m_strLegalCopyright;
	tstring m_strOriginalFileName;
	tstring m_strProductName;
	tstring m_strProductVersion;
	tstring m_strComments;
	tstring m_strLegalTrademarks;
	tstring m_strPrivateBuild;
	tstring m_strSpecialBuild;
};

#endif	//#ifndef __FILE_VERSION_INFO_H__


/// @file StringFormat.h

#pragma once

#include <windows.h>
#include <tchar.h>
#include <string>

class CStringFormat
{
public:
	CStringFormat(void);
	virtual ~CStringFormat(void);

public:
	TCHAR * format(CONST TCHAR * fmt,...);

private:
	TCHAR * m_pMsg;
};

/// @file StringFormat.cpp
#include "StdAfx.h"
#include "StringFormat.h"

CStringFormat::CStringFormat(void)
{
	m_pMsg = NULL;
}

CStringFormat::~CStringFormat(void)
{
	if(m_pMsg)
	{
		delete m_pMsg;
		m_pMsg = NULL;
	}
}

TCHAR * CStringFormat::format(CONST TCHAR * fmt,...)
{
	size_t nLen = 0;
	va_list args;

	va_start(args, fmt);
	nLen = _vscwprintf(fmt, args) + 1;

	if(m_pMsg)
	{
		delete m_pMsg;
		m_pMsg = NULL;
	}

	m_pMsg = new TCHAR[nLen + 1];
	vswprintf_s(m_pMsg, nLen, fmt, args); 

	return m_pMsg;
}

/********************************************************************
*
* Copyright (C) 1999-2000 Sven Wiegand
* Copyright (C) 2000-2001 ToolsCenter
* 
* This file is free software; you can redistribute it and/or
* modify, but leave the headers intact and do not remove any 
* copyrights from the source.
*
* If you have further questions, suggestions or bug fixes, visit 
* our homepage
*
*    http://www.ToolsCenter.org
*
********************************************************************/

#include "stdafx.h"
#include <crtdbg.h>
#include "FileVersionInfo.h"
#include "string/StringFormat.h"

#pragma comment(lib, "Version.lib")

CFileVersionInfo::CFileVersionInfo()
{
	Reset();
}

CFileVersionInfo::~CFileVersionInfo()
{

}

BOOL CFileVersionInfo::GetTranslationId(LPVOID lpData, UINT unBlockSize, WORD wLangId, DWORD &dwId, BOOL bPrimaryEnough/*= FALSE*/)
{
	LPWORD lpwData = 0;

	for (lpwData = (LPWORD)lpData; (LPBYTE)lpwData < ((LPBYTE)lpData)+unBlockSize; lpwData+=sizeof(DWORD))
	{
		if (*lpwData == wLangId)
		{
			dwId = *((DWORD*)lpwData);
			return TRUE;
		}
	}

	if (!bPrimaryEnough)
		return FALSE;

	for (lpwData = (LPWORD)lpData; (LPBYTE)lpwData < ((LPBYTE)lpData) + unBlockSize; lpwData+=sizeof(DWORD))
	{
		if (((*lpwData)&0x00FF) == (wLangId&0x00FF))
		{
			dwId = *((DWORD*)lpwData);
			return TRUE;
		}
	}

	return FALSE;
}

tstring CFileVersionInfo::QueryValue(LPVOID lpData, tstring & strSubBlock, CONST TCHAR * lpcSubBlockKeyName, LPVOID lpInfo, UINT unInfoLen)
{
	tstring strTmp;

	strTmp = strSubBlock + lpcSubBlockKeyName;
	strTmp = (VerQueryValue(lpData, strTmp.c_str(), &lpInfo, &unInfoLen)) ? (TCHAR *)lpInfo : _T("");

	return strTmp;
}

BOOL CFileVersionInfo::Create(HMODULE hModule /*= NULL*/)
{
	tstring	strFilePathName;

	strFilePathName.resize(_MAX_PATH);
	GetModuleFileName(hModule, (TCHAR *)strFilePathName.c_str(), strFilePathName.size());

	return Create(strFilePathName.c_str());
}

BOOL CFileVersionInfo::Create(CONST TCHAR * lpcFilePathName)
{
	UINT	unInfoLen = 0;
	DWORD	dwHandle = 0;
	DWORD	dwFileVersionInfoSize = 0;
	DWORD	dwLangCode = 0;
	LPVOID	lpData = NULL;
	LPVOID	lpInfo = NULL;
	tstring strSubBlock;
	tstring strTmp;
	CStringFormat fmt;

	Reset();

	m_strFilePathName = lpcFilePathName;
	dwFileVersionInfoSize = GetFileVersionInfoSize(m_strFilePathName.c_str(), &dwHandle);
	if (!dwFileVersionInfoSize)
		return FALSE;

	lpData = (LPVOID)new BYTE[dwFileVersionInfoSize];
	if (!lpData)
		return FALSE;

	try
	{
		if (!GetFileVersionInfo(m_strFilePathName.c_str(), dwHandle, dwFileVersionInfoSize, lpData))
			throw FALSE;

		// catch default information
		if (VerQueryValue(lpData, _T("\\"), &lpInfo, &unInfoLen))
		{
			_ASSERT(unInfoLen == sizeof(VS_FIXEDFILEINFO));
			if (unInfoLen == sizeof(VS_FIXEDFILEINFO))
			{
				::memcpy(&m_FileInfo, lpInfo, unInfoLen);
			}
		}

		// find best matching language and codepage
		VerQueryValue(lpData, _T("\\VarFileInfo\\Translation"), &lpInfo, &unInfoLen);
		if (!GetTranslationId(lpInfo, unInfoLen, GetUserDefaultLangID(), dwLangCode, FALSE))
		{
			if (!GetTranslationId(lpInfo, unInfoLen, GetUserDefaultLangID(), dwLangCode, TRUE))
			{
				if (!GetTranslationId(lpInfo, unInfoLen, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), dwLangCode, TRUE))
				{
					if (!GetTranslationId(lpInfo, unInfoLen, MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL), dwLangCode, TRUE))
						// use the first one we can get
						dwLangCode = *((DWORD*)lpInfo);
				}
			}
		}

		strSubBlock = fmt.format(_T("\\StringFileInfo\\%04X%04X\\"), dwLangCode&0x0000FFFF, (dwLangCode&0xFFFF0000)>>16);
		
		// catch string table
		m_strCompanyName =		QueryValue(lpData, strSubBlock, FILE_VERSION_COMPANY_NAME, lpInfo, unInfoLen);
		m_strFileDescription =	QueryValue(lpData, strSubBlock, FILE_VERSION_FILE_DESCRIPTION, lpInfo, unInfoLen);
		m_strFileVersion =		QueryValue(lpData, strSubBlock, FILE_VERSION_FILE_VERSION, lpInfo, unInfoLen);
		m_strInternalName =		QueryValue(lpData, strSubBlock, FILE_VERSION_INTERNAL_NAME, lpInfo, unInfoLen);
		m_strLegalCopyright =	QueryValue(lpData, strSubBlock, FILE_VERSION_LEGAL_COPYRIGHT, lpInfo, unInfoLen);
		m_strOriginalFileName =	QueryValue(lpData, strSubBlock, FILE_VERSION_ORIGINAL_FILENAME, lpInfo, unInfoLen);
		m_strProductName =		QueryValue(lpData, strSubBlock, FILE_VERSION_PRODUCT_NAME, lpInfo, unInfoLen);
		m_strProductVersion =	QueryValue(lpData, strSubBlock, FILE_VERSION_PRODUCT_VERSION, lpInfo, unInfoLen);
		m_strComments =			QueryValue(lpData, strSubBlock, FILE_VERSION_COMMENTS, lpInfo, unInfoLen);
		m_strLegalTrademarks =	QueryValue(lpData, strSubBlock, FILE_VERSION_LEGAL_TRADEMARKS, lpInfo, unInfoLen);
		m_strPrivateBuild =		QueryValue(lpData, strSubBlock, FILE_VERSION_PRIVATE_BUILD, lpInfo, unInfoLen);
		m_strSpecialBuild =		QueryValue(lpData, strSubBlock, FILE_VERSION_SPECIAL_BUILD, lpInfo, unInfoLen);

		delete[] lpData;
	}
	catch (BOOL)
	{
		delete[] lpData;
		return FALSE;
	}

	return TRUE;
}

WORD CFileVersionInfo::GetFileVersion(int iIndex) CONST
{
	WORD wRc = 0;
	switch(iIndex)
	{
	case 0:
		{
			wRc = (WORD)(m_FileInfo.dwFileVersionLS & 0x0000FFFF);
		}
		break;
	case 1:
		{
			wRc = (WORD)((m_FileInfo.dwFileVersionLS & 0xFFFF0000) >> 16);
		}
		break;
	case 2:
		{
			wRc = (WORD)(m_FileInfo.dwFileVersionMS & 0x0000FFFF);
		}
		break;
	case 3:
		{
			wRc = (WORD)((m_FileInfo.dwFileVersionMS & 0xFFFF0000) >> 16);
		}
		break;
	default:
		{
			wRc = 0;
		}
		break;
	}

	return wRc;
}

WORD CFileVersionInfo::GetProductVersion(int iIndex) CONST
{
	WORD wRc = 0;
	switch(iIndex)
	{
	case 0:
		{
			wRc = (WORD)(m_FileInfo.dwProductVersionLS & 0x0000FFFF);
		}
		break;
	case 1:
		{
			wRc = (WORD)((m_FileInfo.dwProductVersionLS & 0xFFFF0000) >> 16);
		}
		break;
	case 2:
		{
			wRc = (WORD)(m_FileInfo.dwProductVersionMS & 0x0000FFFF);
		}
		break;
	case 3:
		{
			wRc = (WORD)((m_FileInfo.dwProductVersionMS & 0xFFFF0000) >> 16);
		}
		break;
	default:
		{
			wRc = 0;
		}
		break;
	}

	return wRc;
}

DWORD CFileVersionInfo::GetFileFlagsMask() CONST
{
	return m_FileInfo.dwFileFlagsMask;
}

DWORD CFileVersionInfo::GetFileFlags() CONST
{
	return m_FileInfo.dwFileFlags;
}

DWORD CFileVersionInfo::GetFileOs() CONST
{
	return m_FileInfo.dwFileOS;
}

DWORD CFileVersionInfo::GetFileType() CONST
{
	return m_FileInfo.dwFileType;
}

DWORD CFileVersionInfo::GetFileSubtype() CONST
{
	return m_FileInfo.dwFileSubtype;
}

VOID CFileVersionInfo::GetFileDate(FILETIME * ft) CONST
{
	ft->dwLowDateTime = m_FileInfo.dwFileDateLS;
	ft->dwHighDateTime = m_FileInfo.dwFileDateMS;
}

TCHAR * CFileVersionInfo::GetCompanyName() CONST
{
	return (TCHAR *)m_strCompanyName.c_str();
}

TCHAR * CFileVersionInfo::GetFileDescription() CONST
{
	return (TCHAR *)m_strFileDescription.c_str();
}

TCHAR * CFileVersionInfo::GetFileVersion() CONST
{
	return (TCHAR *)m_strFileVersion.c_str();
}

TCHAR * CFileVersionInfo::GetInternalName() CONST
{
	return (TCHAR *)m_strInternalName.c_str();
}

TCHAR * CFileVersionInfo::GetLegalCopyright() CONST
{
	return (TCHAR *)m_strLegalCopyright.c_str();
}

TCHAR * CFileVersionInfo::GetOriginalFileName() CONST
{
	return (TCHAR *)m_strOriginalFileName.c_str();
}

TCHAR * CFileVersionInfo::GetProductName() CONST
{
	return (TCHAR *)m_strProductName.c_str();
}

TCHAR * CFileVersionInfo::GetProductVersion() CONST
{
	return (TCHAR *)m_strProductVersion.c_str();
}

TCHAR * CFileVersionInfo::GetComments() CONST
{
	return (TCHAR *)m_strComments.c_str();
}

TCHAR * CFileVersionInfo::GetLegalTrademarks() CONST
{
	return (TCHAR *)m_strLegalTrademarks.c_str();
}

TCHAR * CFileVersionInfo::GetPrivateBuild() CONST
{
	return (TCHAR *)m_strPrivateBuild.c_str();
}

TCHAR * CFileVersionInfo::GetSpecialBuild() CONST
{
	return (TCHAR *)m_strSpecialBuild.c_str();
}

TCHAR * CFileVersionInfo::GetFilePathName()	CONST
{
	return (TCHAR *)m_strFilePathName.c_str();
}

void CFileVersionInfo::Reset()
{
	m_strFilePathName = _T("");
	ZeroMemory(&m_FileInfo, sizeof(VS_FIXEDFILEINFO));
	m_strCompanyName = _T("");
	m_strFileDescription = _T("");
	m_strFileVersion = _T("");
	m_strInternalName = _T("");
	m_strLegalCopyright = _T("");
	m_strOriginalFileName = _T("");
	m_strProductName = _T("");
	m_strProductVersion = _T("");
	m_strComments = _T("");
	m_strLegalTrademarks = _T("");
	m_strPrivateBuild = _T("");
	m_strSpecialBuild = _T("");
}

VOID CFileVersionInfo::ShowFileVersionInfo()
{
	tstring strMsg;
	CStringFormat fmt;

	strMsg = fmt.format(_T("File [%s] information below:\n")\
		_T("%s = %s\n")\
		_T("%s = %s\n")\
		_T("%s = %s\n")\
		_T("%s = %s\n")\
		_T("%s = %s\n")\
		_T("%s = %s\n")\
		_T("%s = %s\n")\
		_T("%s = %s\n")\
		_T("%s = %s\n")\
		_T("%s = %s\n")\
		_T("%s = %s\n"),
		GetFilePathName(),
		_T("m_strCompanyName"), GetCompanyName(),
		_T("m_strFileDescription"), GetFileDescription(),
		_T("m_strFileVersion"), GetFileVersion(),
		_T("m_strInternalName"), GetInternalName(),
		_T("m_strLegalCopyright"), GetLegalCopyright(),
		_T("m_strOriginalFileName"), GetOriginalFileName(),
		_T("m_strProductName"), GetProductName(),
		_T("m_strProductVersion"), GetProductVersion(),
		_T("m_strComments"), GetComments(),
		_T("m_strLegalTrademarks"), GetLegalTrademarks(),
		_T("m_strPrivateBuild"), GetPrivateBuild(),
		_T("m_strSpecialBuild"), GetSpecialBuild());

	_tprintf(_T("%s"), strMsg.c_str());
}

INT CFileVersionInfo::CompareFileVersion(TCHAR * lpcFileVersion)
{
	#define G_DOT_CNT_MAX 3	///< 1.2.3.4, dot number is 3
	INT iRc = 1; ///< 默认结果为: 本类中得到的文件版本号 > 给定的文件版本号
	size_t nPos = 0;
	size_t nIndex = 0;
	ULONGLONG ullMyVersion = ((ULONGLONG)m_FileInfo.dwFileVersionMS << (sizeof(DWORD) * 8)) | (ULONGLONG)m_FileInfo.dwFileVersionLS;
	ULONGLONG ullFileVersion = 0;
	tstring strFileVerPart[G_DOT_CNT_MAX + 1];
	
	if(NULL == lpcFileVersion)
	{
		goto _CompareFileVersion_END;
	}

	while((nIndex <= G_DOT_CNT_MAX) && (L'\0' != *(lpcFileVersion + nPos)))
	{
		if(L'.' == *(lpcFileVersion + nPos))
		{
			nPos++;
			nIndex++;
			continue;
		}

		strFileVerPart[nIndex] += *(lpcFileVersion + nPos++);
	};

	nIndex = 0;
	while(nIndex <= G_DOT_CNT_MAX)
	{
		/// 1 bytes have 8 bits
		ullFileVersion = (ullFileVersion << (sizeof(WORD) * 8)) + _ttoi(strFileVerPart[nIndex++].c_str());
	}

	if(ullMyVersion == ullFileVersion)
	{
		iRc = 0;
	}
	else if(ullMyVersion > ullFileVersion)
	{
		iRc = 1;
	}
	else
	{
		iRc = -1;
	}

_CompareFileVersion_END:
	return iRc;
}




你可能感兴趣的:(File,null,delete,Comments,translation)