MFC程序版本自动升级更新

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

MFC程序版本自动升级更新_第1张图片

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

MFC程序版本自动升级更新_第2张图片

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 
#include 

#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、更多源码您可以下载查看。

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

 

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

你可能感兴趣的:(MFC)