MFC程序版本自动升级更新

1、自动升级需要实现两个exe程序的交替启动,需要一个主程序和一个升级程序;在一个解决方案中创建两个项目,一个是你的主程序,另一个为你的升级程序;第二个程序创建选择添加到解决方案,同时选中你要添加的位子(即主程序路径)。

2、创建成功后的解决方案;Agent为我的升级程序,AutoUpdate为我的主程序。

3、创建本地版本文件和服务端版本文件;

本地版本文件:

VersionInfo.ini

[INIURL]
iniurl=http://220.231.141.28:8088/HDMFCUPDATE/AutoUpdate/AgentVersionInfo.ini
[MAINVER]
mainver=1.0
[VERDATE]
verdate=2018-03-09 09:36:52
[AUTHOR]
author=kung

服务端版本文件:

AgentVersionInfo.ini

[INIURL]
iniurl=http://220.231.141.28:8088/HDMFCUPDATE/AutoUpdate/AgentVersionInfo.ini
[MAINVER]
mainver=2.0
[VERDATE]
verdate=2018-03-09 09:36:52
[AUTHOR]
author=kung

[FILECOUNT]
filecount=7
[FILENAME]
filename1=AutoUpdate.exe
filename2=test/a6.txt
filename3=test/a7.txt
filename4=test/a8.txt
filename5=test/a9.txt
filename6=test/test/a10.txt
filename7=test/test/a11.txt
[FILEURL]
fileurl1=http://220.231.141.28:8088/HDMFCUPDATE/AutoUpdate/20180301/AutoUpdate.exe,B84DACA51346BBD1F074C97F60ACAEE9
fileurl2=http://220.231.141.28:8088/HDMFCUPDATE/AutoUpdate/20180301/test/a6.txt,1B6D5D3EE41909A1BD0880F72890B5F7
fileurl3=http://220.231.141.28:8088/HDMFCUPDATE/AutoUpdate/20180301/test/a7.txt,1B6D5D3EE41909A1BD0880F72890B5F7
fileurl4=http://220.231.141.28:8088/HDMFCUPDATE/AutoUpdate/20180301/test/a8.txt,1B6D5D3EE41909A1BD0880F72890B5F7
fileurl5=http://220.231.141.28:8088/HDMFCUPDATE/AutoUpdate/20180301/test/a9.txt,1B6D5D3EE41909A1BD0880F72890B5F7
fileurl6=http://220.231.141.28:8088/HDMFCUPDATE/AutoUpdate/20180301/test/test/a10.txt,1B6D5D3EE41909A1BD0880F72890B5F7
fileurl7=http://220.231.141.28:8088/HDMFCUPDATE/AutoUpdate/20180301/test/test/a11.txt,1B6D5D3EE41909A1BD0880F72890B5F7

4、再主程序中添加代码,读取服务端的升级文件的版本号和版本文件进行比对;如果本地版本低的话,启动升级程序进行文件下载更新,否则不更新,通过线程的方式检查版本。

VersionUpdate.h

#pragma once
class VersionUpdate
{
public:
	VersionUpdate(void);
	~VersionUpdate(void);

	//自动更新线程
	static UINT ThreadCheckVer(LPVOID pParam);	
	//下载包含更新版本号的配置文件
	static INT DownloadIniFile(CString strUrl);
	//下载指定地址的文件
	static INT DownloadFile(const CString strUrl,const CString strSavePath);
};

VersionUpdate.cpp

#include "StdAfx.h"
#include "VersionUpdate.h"
#include <WinBase.h>
#include <afxinet.h>

#define BUF_SIZE	2048  
#define WM_UPDATE		WM_USER+100

VersionUpdate::VersionUpdate(void)
{
}


VersionUpdate::~VersionUpdate(void)
{
}

//自动更新线程
UINT VersionUpdate::ThreadCheckVer(LPVOID lpParam)
{
	CString strFileName_ini,strControlName;
	//从配置文件读入当前版本号
	char str[MAX_PATH];
	GetModuleFileName(NULL,str,128);
	CString exePath;
	exePath = str;
	CString programFolder;
	programFolder = exePath.Mid(0,exePath.ReverseFind('\\'))+"\\";

	//char pBuf[MAX_PATH];
	//GetCurrentDirectory(MAX_PATH,pBuf);
	//strcat_s(pBuf,"\\VersionInfo.ini");
	strFileName_ini = programFolder + "VersionInfo.ini";

	//获取当前配置文件的版本号
	::GetPrivateProfileString("MAINVER","mainver",NULL,strControlName.GetBuffer(128),128,strFileName_ini);
	strControlName.ReleaseBuffer();
	double flCurVer = atof(strControlName);			//保存当前版本号

	//获取下载配置文件的地址
	strControlName = "";
	::GetPrivateProfileString("INIURL","iniurl",NULL,strControlName.GetBuffer(MAX_PATH),MAX_PATH,strFileName_ini);
	strControlName.ReleaseBuffer();
	CString strUrl = strControlName;
	if (strUrl.GetLength() == 0){
		AfxMessageBox("VersionInfo.ini文件有误,请手动下载新版本!");
		return 0;
	}

	//下载包含更新版本号的配置文件
	INT DownloadFileResult =  DownloadIniFile(strUrl);
	if(DownloadFileResult != 0){
		//AfxMessageBox("检测新版本失败!如果软件不能使用请手动下载更新!");
		return 0;
	}

	//从下载来的配置文件读入最新版本号
	strFileName_ini.Replace("VersionInfo.ini","AgentVersionInfo.ini");
	::GetPrivateProfileString("MAINVER","mainver",NULL,strControlName.GetBuffer(128),128,strFileName_ini);
	strControlName.ReleaseBuffer();
	double flNewVer = atof(strControlName);

	//对比版本号	如果大于本地版本就启动更新程序进行更新  更新成功就写入新版本到pz.ini里
	if( flNewVer > flCurVer){
		//启动UpDate.exe来更新Dll
		char pBuf[MAX_PATH];
		GetCurrentDirectory(MAX_PATH,pBuf);
		strcat_s(pBuf,"\\Agent.exe");
		CString strPath = pBuf;
		HINSTANCE hID = ShellExecuteA(NULL,"open",strPath,NULL,NULL,SW_SHOWNORMAL);
		if ((int)hID <= 32)
		{
			AfxMessageBox("程序目录下缺少升级程序Agent.exe!,请重新下载完整版本!");
			return 0;
		}
		//关闭本程序
		ExitProcess(0);
	}else{
		::DeleteFile(strFileName_ini);						//删除下载来的配置文件
	}
	return 0;		
}

//下载包含更新版本号的配置文件
INT  VersionUpdate::DownloadIniFile(CString strUrl)
{
	CString strFileName_ini;

	char pBuf[MAX_PATH];
	GetCurrentDirectory(MAX_PATH,pBuf);
	strcat_s(pBuf,"\\AgentVersionInfo.ini");
	strFileName_ini = pBuf;

	char buf[BUF_SIZE] = {0};  
	char url[MAX_PATH];
	strcat_s(url,strUrl);

	return DownloadFile(url,strFileName_ini);
}

//下载指定地址的文件
/*
0:成功下载保存
-1:URL不正确
-2:建立网络连接失败
-3:向服务器发起GET请求失败
-4:服务器不接受请求
-5:参数一不能为空
-6:参数二不能为空
-7:保存文件时创建或写入文件失败
*/
INT VersionUpdate::DownloadFile(const CString strUrl,const CString strSavePath)
{
	//检查传入的两个参数
	if (strUrl.IsEmpty())
		return -5;
	if (strSavePath.IsEmpty())
		return -6;

	unsigned short nPort;        //用于保存目标HTTP服务端口
	CString strServer, strObject;    //strServer用于保存服务器地址,strObject用于保存文件对象名称
	DWORD dwServiceType,dwRet;        //dwServiceType用于保存服务类型,dwRet用于保存提交GET请求返回的状态号

	//解析URL,获取信息
	if(!AfxParseURL(strUrl, dwServiceType, strServer, strObject, nPort)){
		//解析失败,该Url不正确
		return -1;
	}
	//创建网络连接对象,HTTP连接对象指针和用于该连接的HttpFile文件对象指针,注意delete
	CInternetSession intsess;
	CHttpFile *pHtFile = NULL;
	CHttpConnection *pHtCon = NULL;

	intsess.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT, 1000 * 20);  //连接超时
	intsess.SetOption(INTERNET_OPTION_CONNECT_BACKOFF, 1000);       //两次重试之间的间隔时间
	intsess.SetOption(INTERNET_OPTION_CONNECT_RETRIES, 1);          // 2次重试
	intsess.SetOption(INTERNET_OPTION_SEND_TIMEOUT,6000);			//发送请求的超时时间
	intsess.SetOption(INTERNET_OPTION_RECEIVE_TIMEOUT,6000);		//接受数据的超时时间

	try{		
		//建立网络连接
		pHtCon = intsess.GetHttpConnection(strServer,nPort);
		if(pHtCon == NULL){
			//建立网络连接失败
			intsess.Close();
			return -2;
		}
		//发起GET请求
		pHtFile = pHtCon->OpenRequest(CHttpConnection::HTTP_VERB_GET,strObject);
		if(pHtFile == NULL)
		{
			//发起GET请求失败
			intsess.Close();
			delete pHtCon;
			pHtCon = NULL;
			return -3;
		}
		//提交请求
		pHtFile->SendRequest();
		//获取服务器返回的状态号
		pHtFile->QueryInfoStatusCode(dwRet);
		if (dwRet != HTTP_STATUS_OK){
			//服务器不接受请求
			intsess.Close();
			delete pHtCon;pHtCon = NULL;
			delete pHtFile;pHtFile = NULL;
			return -4;
		}
	}catch (CInternetException* e){
		e->Delete();
		intsess.Close();
		delete pHtCon;pHtCon = NULL;
		delete pHtFile;pHtFile = NULL;
		return -2;
	}	

	//获取文件大小
	UINT nFileLen = (UINT)pHtFile->GetLength();
	DWORD dwRead = 1;        //用于标识读了多少,为1是为了进入循环
	//创建缓冲区
	CHAR *szBuffer = new CHAR[nFileLen+1];
	TRY {
		//创建文件
		CFile PicFile(strSavePath,CFile::modeCreate|CFile::modeWrite|CFile::shareExclusive);
		while(dwRead>0)
		{  
			//清空缓冲区
			memset(szBuffer,0,(size_t)(nFileLen+1));
			//读取到缓冲区
			dwRead = pHtFile->Read(szBuffer,nFileLen); 
			//写入到文件
			PicFile.Write(szBuffer,dwRead);
		}
		//关闭文件
		PicFile.Close();
		//释放内存
		delete []szBuffer;
		delete pHtFile;
		delete pHtCon;
		//关闭网络连接
		intsess.Close();
	}
	CATCH(CFileException,e)
	{
		//释放内存
		delete []szBuffer;
		delete pHtFile;
		delete pHtCon;
		//关闭网络连接
		intsess.Close();
		return -7;            //读写文件异常
	}
	END_CATCH
		return 0;
}

5、Agent升级程序需要添加一个列表对话框,用于显示文件下载进度;

6、Agent程序先根据现在的升级版本文件,显示需要更新的文件列表、文件大小,读取版本文件的内容,同时获取本地文件的MD5,比对MD5,如果不同则根据版本文件的地址下载覆盖本地文件,同时显示下载进度;升级完成删除下载的远端版本文件,然后启动主程序,关闭升级程序;

7、更多源码您可以下载查看。

源码下载地址:点击打开链接

 

仅此供给大家,在大家有这方面的需求时,少走弯路!如果对大家有用,请大家多多点赞支持!

### 回答1: MFC (Microsoft Foundation Class) 是微软提供的一组应用程序框架,其可以帮助程序员快速开发 Microsoft Windows 平台下的应用程序。其中,自动更新资源是 MFC 中的一个重要功能,其可以帮助软件自动升级,并更新最新的版本信息。 在 MFC 中使用自动更新资源需要经过以下步骤: 首先,需要在资源文件中定义自动更新资源相关的信息,例如版本信息、下载地址等等。然后,在应用程序初始化时,可以调用函数 EnableVersionCheck() 来启用自动更新资源的功能。在应用程序运行过程中,MFC 将会自动检测服务器上的最新版本,并提示用户是否需要升级。如果用户同意升级MFC 将会自动下载最新的程序,并安装升级。 如果需要在自动更新资源中更新版本信息,可以通过以下步骤实现: 1. 修改资源文件中的版本号,例如修改 VERTIONINFO 中的 FILEVERSION 和 PRODUCTVERSION 字段。 2. 在应用程序中调用函数 AfxSetResourceHandle() 来指定使用的资源句柄。 3. 调用函数 AfxLoadLibrary() 来动态加载 DLL,以便更新程序版本信息。 4. 使用函数 UpdateResource() 来修改版本资源中的信息,例如修改版本号、文件描述等等。 5. 最后,调用函数 FreeLibrary() 来卸载 DLL 文件。 以上就是在 MFC自动更新资源中更新版本信息的方法。需要注意的是,为了确保自动更新资源的可靠性和安全性,程序员需要保证下载的程序经过验证,并进行合理的安全措施。 ### 回答2: 在MFC中,实现自动更新资源中的版本信息可以通过以下步骤: 1. 在工程资源中添加版本信息,包括文件版本、产品版本等各种版本属性。 2. 在代码中使用CWinApp类中的GetAppVersion函数来获取当前程序版本信息。 3. 在自动更新程序中,通过读取从服务器上下载下来的版本信息文件,获取最新的版本信息。 4. 对比本地程序和最新版本版本信息,如果本地程序版本较旧,则提示用户是否更新程序。 5. 如果用户确认要更新程序,先备份原程序文件,然后下载最新版本程序文件,并替换原程序文件。 6. 更新完成后,再次运行程序时,就可以使用新的版本信息了。 需要注意的是,自动更新程序需要有足够的权限来替换原程序文件,否则更新过程可能会受到阻碍。同时还需要保证服务器上的版本信息文件和可执行程序版本信息一一对应,否则可能会出现版本不兼容的情况。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kung900519

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值