// 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; }