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

发布时间:2023年12月30日

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

// @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());
	}

END

文章来源:https://blog.csdn.net/LostSpeed/article/details/135307343
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。