MFC - 类封装 - 取工程内部的程序版本信息

文章目录

    • [MFC - 类封装 - 取工程内部的程序版本信息](#MFC - 类封装 - 取工程内部的程序版本信息)
    • 概述
    • class用法
    • [class实现 - CInternalVersionInfo.h](#class实现 - CInternalVersionInfo.h)
    • [class实现 - CInternalVersionInfo.cpp](#class实现 - CInternalVersionInfo.cpp)
    • 设置程序标题
    • END

MFC - 类封装 - 取工程内部的程序版本信息

概述

在整理程序内部显示版本信息相关的实现.

程序在开发中的时候, 随便硬编码.

现在准备和程序rc资源中的版本信息对应起来, 这样的话, 程序升级后, 只需要改rc中的信息, 不用担心程序中用到的版本信息的硬编码问题.

以前也见过这种类实现, 没存货. 用了2个小时, 自己封装了一个类. 好用.

class用法

类变量定义

c 复制代码
CInternalVersionInfo* m_pFileVersionInfo;

主程序初始化时(和UI无关, 可以尽早初始化), 初始化类变量.

c 复制代码
CMainDlg::CMainDlg(CWnd* pParent /*=nullptr*/)
{
m_pFileVersionInfo = new CInternalVersionInfo(NULL); // 参数1是BlockHeader的name, 默认是中文rc => _T("080404b0")  
// 在类构造函数中, 就取到了工程版本信息
// 等要用工程版本信息时, 就拿这个类指针取值来用
}

如果是其他语言rc, 可以看工程实际rc的Block Header的实际值.

程序销毁前, 删除new出来的类实例

c 复制代码
void CMoneyCostParserDlg::OnDestroy()
{
	__super::OnDestroy();
	// ...
	if (NULL != m_pFileVersionInfo)
	{
		delete m_pFileVersionInfo;
		m_pFileVersionInfo = NULL;
	}
}

class实现 - CInternalVersionInfo.h

c 复制代码
// @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
//END

class 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

c 复制代码
// @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(), 当然用到时再拼字符串也行, 不过麻烦.

c 复制代码
BOOL CMoneyCostParserDlg::OnInitDialog()
{
	// ...
	// TODO: 在此添加额外的初始化代码
	if (NULL != m_pFileVersionInfo)
	{
		this->SetWindowText(m_pFileVersionInfo->getAppTitle());
	}

END

相关推荐
Zfox_13 分钟前
【Linux】进程信号全攻略(二)
linux·运维·c语言·c++
起名字真南31 分钟前
【OJ题解】C++实现字符串大数相乘:无BigInteger库的字符串乘积解决方案
开发语言·c++·leetcode
少年负剑去31 分钟前
第十五届蓝桥杯C/C++B组题解——数字接龙
c语言·c++·蓝桥杯
cleveryuoyuo32 分钟前
AVL树的旋转
c++
神仙别闹1 小时前
基于MFC实现的赛车游戏
c++·游戏·mfc
小c君tt1 小时前
MFC中 error C2440错误分析及解决方法
c++·mfc
木向2 小时前
leetcode92:反转链表||
数据结构·c++·算法·leetcode·链表
阿阿越2 小时前
算法每日练 -- 双指针篇(持续更新中)
数据结构·c++·算法
hunandede2 小时前
FFmpeg存放压缩后的音视频数据的结构体:AVPacket简介,结构体,函数
c++
hunandede2 小时前
FFmpeg 4.3 音视频-多路H265监控录放C++开发十三:将AVFrame转换成AVPacket。视频编码,AVPacket 重要函数,结构体成员学习
c++·ffmpeg·音视频