最近在整理东西,打算把一些小东西分类整理下,与大家分享一下:
很早以前用MFC开始在做工业软件时,经常会遇到版本备份啊什么之类的问题,那时候,不太懂,后来研究了一下API,发现了如何读取VS_VERSION_INFO。
我们知道,MFC生成的exe的所有信息都是在RC\Version\VS_VERSION_INFO里设置的,我们只要在CAboutDlg里,把PRODUCTVERSION的信息读出来,在CAboutDlg里显示出来,这样只需要每次在VVI里修改相关信息,而不用再去考虑相关信息的一致性了,因为信息源只有这一个。
新建一个CMiyaVersion类,
MiyaVersion.h文件:
接口函数为GetFileVersionInfo以及GetValue,使用时,要先调用GetFileVersionInfo获取exe的所有版本信息即:m_pVersionInfo,当然这里提供一个常用的返回信息版本号:lpszVersion,若想获得其它信息,可使用GetValue去获取
- CompanyName:获取公:司名称
- FileDescription:
- FileVersion:
- InternalName:
- LegalCopyright:
- OriginalFilename:
- ProductName:
- ProductVersion:
#pragma once namespace MiyaVersion { #include <shlwapi.h> #pragma comment(linker, "/defaultlib:version.lib") class CMiyaVersion : public VS_FIXEDFILEINFO { public: CMiyaVersion(); virtual ~CMiyaVersion(); public: bool GetFileVersionInfo(LPCTSTR lpszModuleName, LPCTSTR lpszVersion); CString GetValue(LPCTSTR lpKeyName); protected: static bool DllGetVersion(LPCTSTR lpszModuleName, DLLVERSIONINFO& dvi); protected: BYTE* m_pVersionInfo; // all version info typedef struct tag_TRANSLATION { WORD langID; // language ID WORD charset; // character set (code page) } TRANSLATION, *LPTRANSLATION; TRANSLATION m_translation; }; }
MiyaVersion.cpp文件
#include "stdafx.h" #include "MiyaVersion.h" using namespace MiyaVersion; // // Construction/Destruction // CMiyaVersion::CMiyaVersion() { m_pVersionInfo = NULL; } CMiyaVersion::~CMiyaVersion() { if (m_pVersionInfo != NULL) { delete []m_pVersionInfo; m_pVersionInfo = NULL; } } bool CMiyaVersion::GetFileVersionInfo(LPCTSTR lpszModuleName, LPCTSTR lpszVersion) { // default = ANSI code page m_translation.charset = 1252; memset((VS_FIXEDFILEINFO*)this, 0, sizeof(VS_FIXEDFILEINFO)); // get module handle TCHAR chFileName[_MAX_PATH] = {0}; HMODULE hModule = ::GetModuleHandle(lpszModuleName); if (hModule==NULL && lpszModuleName!=NULL) { return false; } // get module file name DWORD dwLen = GetModuleFileName(hModule, chFileName, sizeof(chFileName)/sizeof(chFileName[0])); if (dwLen <= 0) { return false; } // read file version info DWORD dwDummyHandle = 0; // will always be set to zero dwLen = GetFileVersionInfoSize(chFileName, &dwDummyHandle); if (dwLen <= 0) { return false; } if (m_pVersionInfo != NULL) { delete []m_pVersionInfo; m_pVersionInfo = NULL; } m_pVersionInfo = new BYTE[dwLen]; // allocate version info if (!::GetFileVersionInfo(chFileName, 0, dwLen, m_pVersionInfo)) { if (m_pVersionInfo != NULL) { delete []m_pVersionInfo; m_pVersionInfo = NULL; } return false; } LPVOID lpvi = NULL; UINT nLen = 0; if (!VerQueryValue(m_pVersionInfo, _T("\\"), &lpvi, &nLen)) { if (m_pVersionInfo != NULL) { delete []m_pVersionInfo; m_pVersionInfo = NULL; } return false; } // copy fixed info to myself, which am derived from VS_FIXEDFILEINFO *(VS_FIXEDFILEINFO*)this = *(VS_FIXEDFILEINFO*)lpvi; // Get translation info if (VerQueryValue(m_pVersionInfo, _T("\\VarFileInfo\\Translation"), &lpvi, &nLen) && nLen >= 4) { m_translation = *(TRANSLATION*)lpvi; } CString strVersion(_T("")); strVersion.Format(_T("%d.%d.%d.%d"), \ HIWORD(this->dwFileVersionMS), LOWORD(this->dwFileVersionMS), \ HIWORD(this->dwFileVersionLS), LOWORD(this->dwFileVersionLS)); UINT nTemp = wcslen(strVersion)+1; lstrcpyn((LPTSTR)lpszVersion, strVersion, nTemp); return (dwSignature == VS_FFI_SIGNATURE); } CString CMiyaVersion::GetValue(LPCTSTR lpKeyName) { CString strVal(_T("")); if (m_pVersionInfo != NULL) { CString strQuery; strQuery.Format(_T("\\StringFileInfo\\%04x%04x\\%s"), m_translation.langID, m_translation.charset, lpKeyName); LPCTSTR pVal = NULL; UINT nLenVal = 0; if (VerQueryValue(m_pVersionInfo, (LPTSTR)(LPCTSTR)strQuery, (LPVOID*)&pVal, &nLenVal)) { strVal = pVal; } } return strVal; } typedef HRESULT (CALLBACK* DLLGETVERSIONPROC)(DLLVERSIONINFO *); bool CMiyaVersion::DllGetVersion(LPCTSTR lpszModuleName, DLLVERSIONINFO& dvi) { HINSTANCE hInst = LoadLibrary(lpszModuleName); if (hInst == NULL) { return false; } DLLGETVERSIONPROC pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hInst, ("DllGetVersion")); if (pDllGetVersion == NULL) { return false; } memset(&dvi, 0, sizeof(dvi)); // clear dvi.cbSize = sizeof(dvi); // set size for Windows return SUCCEEDED((*pDllGetVersion)(&dvi)); }