文章目录
- MFC - 类封装 - 取工程内部的程序版本信息
- 概述
- class用法
- class实现 - CInternalVersionInfo.h
- class实现 - CInternalVersionInfo.cpp
- 设置程序标题
- END
MFC - 类封装 - 取工程内部的程序版本信息
概述
在整理程序内部显示版本信息相关的实现.
程序在开发中的时候, 随便硬编码.
现在准备和程序rc资源中的版本信息对应起来, 这样的话, 程序升级后, 只需要改rc中的信息, 不用担心程序中用到的版本信息的硬编码问题.
以前也见过这种类实现, 没存货. 用了2个小时, 自己封装了一个类. 好用.
class用法
类变量定义
CInternalVersionInfo* m_pFileVersionInfo;
主程序初始化时(和UI无关, 可以尽早初始化), 初始化类变量.
CMainDlg::CMainDlg(CWnd* pParent /*=nullptr*/)
{
m_pFileVersionInfo = new CInternalVersionInfo(NULL); // 参数1是BlockHeader的name, 默认是中文rc => _T("080404b0")
// 在类构造函数中, 就取到了工程版本信息
// 等要用工程版本信息时, 就拿这个类指针取值来用
}
如果是其他语言rc, 可以看工程实际rc的Block Header的实际值.
程序销毁前, 删除new出来的类实例
void CMoneyCostParserDlg::OnDestroy()
{__super::OnDestroy();// ...if (NULL != m_pFileVersionInfo){delete m_pFileVersionInfo;m_pFileVersionInfo = NULL;}
}
class实现 - CInternalVersionInfo.h
// @file CInternalVersionInfo.h
// @brief 取工程内部资源中的文件版本的所有信息, 取的信息等同于右键文件属性看到的文件版本信息#ifndef __CINTERNALVERSIONINFO_H__
#define __CINTERNALVERSIONINFO_H__/
Version
//
//VS_VERSION_INFO VERSIONINFO
// FILEVERSION 1,0,0,1
// PRODUCTVERSION 1,0,0,1
// FILEFLAGSMASK 0x3fL
//#ifdef _DEBUG
// FILEFLAGS 0x1L
//#else
// FILEFLAGS 0x0L
//#endif
// FILEOS 0x40004L
// FILETYPE 0x1L
// FILESUBTYPE 0x0L
//BEGIN
// BLOCK "StringFileInfo"
// BEGIN
// BLOCK "080404b0"
// BEGIN
// VALUE "CompanyName", "xx公司"
// VALUE "FileDescription", "xxProg"
// VALUE "FileVersion", "1.0.0.1"
// VALUE "InternalName", "xx.exe"
// VALUE "LegalCopyright", "(C) xx公司 20xx-2023"
// VALUE "OriginalFilename", "xx.exe"
// VALUE "ProductName", "progName"
// VALUE "ProductVersion", "1.0.0.1"
// END
// END
// BLOCK "VarFileInfo"
// BEGIN
// VALUE "Translation", 0x804, 1200
// END
//ENDclass CInternalVersionInfo
{
public:CInternalVersionInfo(const TCHAR* pszBlockHeder);virtual ~CInternalVersionInfo();// 公开的接口// 程序顶部显示给用户看的程序标题(效果 => xx程序 Vx.x.x.x)CString getAppTitle() { return (m_csProductName + _T(" V") + m_csProductVersion); }// 共有成员CString m_csCompanyName; // VALUE "CompanyName", "xx公司" => "xx公司"CString m_csFileDescription; // VALUE "FileDescription", "xxProg" => "xxProg"CString m_csFileVersion; // VALUE "FileVersion", "1.0.0.1" => "1.0.0.1"CString m_csInternalName; // VALUE "InternalName", "xx.exe" => "xx.exe"CString m_csLegalCopyright; // VALUE "LegalCopyright", "(C) xx公司 20xx-2023" => "(C) xx公司 20xx-2023"CString m_csOriginalFilename; // VALUE "OriginalFilename", "xx.exe" => "xx.exe"CString m_csProductName; // VALUE "ProductName", "progName" => "progName"CString m_csProductVersion; // VALUE "ProductVersion", "1.0.0.1" => "1.0.0.1"private:const TCHAR* getBlockHeader() { return (LPCWSTR)m_csBlockHeader; }CString m_csBlockHeader; // BLOCK "080404b0" => "080404b0"CString get_FileInfoValue(BYTE* byData, const TCHAR* pszValueName);
};#endif // #ifndef __CINTERNALVERSIONINFO_H__
class实现 - CInternalVersionInfo.cpp
// @file CInternalVersionInfo.cpp#include "pch.h" // 其他缺的头文件放在预编译头文件中 e.g. framework.h#include <winver.h>
#pragma comment(lib, "Version.lib")#include "CInternalVersionInfo.h"CInternalVersionInfo::CInternalVersionInfo(const TCHAR* pszBlockHeder): m_csBlockHeader(_T("080404b0"))
{TCHAR szAppName[MAX_PATH];DWORD dwSize = 0;DWORD dwHandle = 0;BYTE* byData = NULL;TCHAR* lpVers = NULL;unsigned int uLen = 0;CString csQuery;CString csTmp;if (NULL != pszBlockHeder){m_csBlockHeader = pszBlockHeder;}_stprintf(szAppName, _T("%s.exe"), AfxGetApp()->m_pszExeName);dwSize = GetFileVersionInfoSize(szAppName, &dwHandle);byData = new BYTE[dwSize + 0x10];if (NULL != byData){memset(byData, 0, dwSize + 0x10);GetFileVersionInfo(szAppName, NULL, dwSize, byData);// VALUE "CompanyName", "xx公司"m_csCompanyName = get_FileInfoValue(byData, _T("CompanyName"));// VALUE "FileDescription", "xxProg"m_csFileDescription = get_FileInfoValue(byData, _T("FileDescription"));// VALUE "FileVersion", "1.0.0.1"m_csFileVersion = get_FileInfoValue(byData, _T("FileVersion"));// VALUE "InternalName", "MoneyCostParser.exe"m_csInternalName = get_FileInfoValue(byData, _T("InternalName"));// VALUE "LegalCopyright", "(C) xx公司 2019-2023"m_csLegalCopyright = get_FileInfoValue(byData, _T("LegalCopyright"));// VALUE "OriginalFilename", "xx.exe"m_csOriginalFilename = get_FileInfoValue(byData, _T("OriginalFilename"));// VALUE "ProductName", "电商账单分析处理"m_csProductName = get_FileInfoValue(byData, _T("ProductName"));// VALUE "ProductVersion", "1.0.0.1"m_csProductVersion = get_FileInfoValue(byData, _T("ProductVersion"));delete[]byData;}
}CInternalVersionInfo::~CInternalVersionInfo()
{}CString CInternalVersionInfo::get_FileInfoValue(BYTE* byData, const TCHAR* pszValueName)
{CString csQuery;CString csRc;TCHAR* lpVers = NULL;unsigned int uLen = 0;_ASSERT(NULL != pszValueName);csQuery.Format(_T("\\StringFileInfo\\%s\\%s"), getBlockHeader(), pszValueName);_ASSERT(NULL != byData);VerQueryValue(byData, (LPCWSTR)csQuery, (void**)&lpVers, &uLen);if ((uLen > 0) && (NULL != lpVers)){csRc = lpVers;}return csRc;
}
设置程序标题
要在程序标题上显示一个和实际程序名称版本一致的信息. 在类中封了一个常用函数getAppTitle(), 当然用到时再拼字符串也行, 不过麻烦.
BOOL CMoneyCostParserDlg::OnInitDialog()
{// ...// TODO: 在此添加额外的初始化代码if (NULL != m_pFileVersionInfo){this->SetWindowText(m_pFileVersionInfo->getAppTitle());}