PS:文章是从本人sina博客搬移过来:
win32 自动更新的一种方案
ps:此只是一个思路,上不了台面的哈;
因工作需要,需要做出一个自动更新的方案;主要是作为内部使用,因此需要考虑的因素并不多。YI给出了其使用C#做的一些方法,然后提示了我应该怎么去做自动更新。其实个人感觉自动更新大体的思路都是一样。画出思路丢在了工作笔记本上,然后又是其他的事耽搁了,而上头亦没有做出什么要求,汗,直到那天YI给我看他的年终报告,才知道YI把这事记上了,而我有没有主动去弄,汗,有点对不起YI,于是上午就狠狠的弄了下把方案演示做给了YI.给出个交代.......
具体思路:程序启动时,开启一个线程A,A线程用来读取运行程序的版本号,并获取更新地址上保存的版本信息,然后比较版本是否有更新,如果有更新,则提示用户是否选择更新。如果选择了更新,那么,开启预设定好的下载进程,关闭正在运行的程序(好的更新程序会保存当前的工作,或者保存当前工作的配置等,更新完毕后悔重新启动原有程序,在此只是做一个方案,不要求有如此高的功能),下载完成后,覆盖原有的文件,启动安装进程。当然这是一种不规范的方法。仅供参考;贴上程序;程序一:模拟主函数运行,线程检测版本信息。程序二:下载存放在服务器上已更新的文件,覆盖原有文件,重新安装;
程序一:
#pragmaonce
#pragmacomment(lib,"Wininet.lib")
#pragmacomment(lib,"Version.lib")
#include
#include
#include
#include
#defineMAX 1024
usingnamespace std;
DWORDWINAPI StartCheckVersion(LPVOID lpParam);
bool Compareversion(char* Buff); //比较版本信息;
WCHAR* GetAppVersion();//得到程序的版本信息;
boolStartDownloadNewVersion();//启动下载新版本
intmain(int argv,char * argc[])
{
HANDLEhCheckThread;
DWORDdwThreadId;
hCheckThread=CreateThread( //启动线程函数StartCheckVersion来检查存放在服务器上的版本信息;
NULL,
0,
StartCheckVersion,
NULL,
0,
&dwThreadId);
if(hCheckThread)
{
while(1)
{
Sleep(1000);
cout<<"testthe main function :is running!"<<endl;
}
}
return0;
}
DWORDWINAPI StartCheckVersion(LPVOID lpParam) //线程函数,检测版本信息;
{
charBuff[MAX]={0};
LPCWSTRversionaddress=_T("http://localhost/WebService/Version.txt"); //在本地的上发布了一个web,存放了最新的版本信息;
DWORDdwRead;
HINTERNET hInet=NULL,hfile=NULL;
boolnewversion=false;
hInet=InternetOpen(
_T("Test"),
INTERNET_OPEN_TYPE_DIRECT,
NULL,
NULL,
0);
if(hInet)
{
hfile=InternetOpenUrl(
hInet,
versionaddress,
NULL,
0,
0,
0);
if(hfile)
{
InternetReadFile( //取得服务器上的版本信息,存放在Buff中;
hInet,
Buff,
20,
&dwRead);
if(dwRead)
{
newversion=Compareversion(Buff); //比较版本信息;
}
if(newversion)
{
if(::MessageBox(NULL,_T("检测到有版本更新,是否需要下载?"),_T("更新提示"),MB_OKCANCEL)==IDOK)
{
//以下是启动新进程所必须的两个结体,具体含意查MSDN;
STARTUPINFOsi;
PROCESS_INFORMATIONpi;
ZeroMemory(&si,sizeof(si));
si.cb=sizeof(si);
si.wShowWindow=SW_SHOWNORMAL; //设置窗口为正常显示;
ZeroMemory(&pi,sizeof(pi));
if(!CreateProcess(
_T("C:\\Download.exe"), //设置为我们写好的下载程序;
NULL,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&si,
&pi))
{
cout<<"CreateProcess failed "<<GetLastError()<<endl;
return0;
}
InternetCloseHandle(hfile);
InternetCloseHandle(hInet);
exit(0); //结束当前程序;
}
}
}
}
else
{
cout<<"internetopenerror"<<endl;
InternetCloseHandle(hfile); //关闭句柄动作,
InternetCloseHandle(hInet);
return0;
}
return 0;
}
boolCompareversion(char *Buff)
{
WCHAR *Version;
WORDdwMinSize;
WCHAR*T_Version,*T_WBuff;
dwMinSize=MultiByteToWideChar(CP_ACP,0,Buff,-1,NULL,0);
WCHAR*WBuff=newWCHAR[dwMinSize];
MultiByteToWideChar(CP_ACP,0,Buff,-1,WBuff,dwMinSize);
Version=GetAppVersion();//得到指定的程序的版本信息;
T_Version=Version;
T_WBuff=WBuff;
while((*T_Version)!='\0') //这里仅仅做了简单的相同匹配来判断是否有更新;
{
if((*T_Version++)!=(*T_WBuff++))
{
deleteWBuff;
delete Version;
returntrue; //如果版本不一样,则返回true,通知程序有新版本;
}
}
deleteWBuff;
delete Version;
return false;
}
WCHAR*GetAppVersion()
{
struct String{
WCHARFileVersion[20];
}*VersionString;
DWORDlpdwhand;
DWORD FileVersionSize;
WCHAR*Version;
WCHARFILEPATH[]=_T("d:\\Reader.exe"); //这里是我测试的一个程序;
FileVersionSize=GetFileVersionInfoSize(FILEPATH,&lpdwhand); //获得指定程序的版本属性文件信息;
Version=newWCHAR[FileVersionSize+1];
LPVOID lpBuffer=NULL;
UINTuLen=0;
WCHAR*VersionInfo;
VerQueryValue(Version,TEXT("\\StringFileInfo\\040904e4\\FileVersion"),(LPVOID*)&VersionString,&uLen); //遍历出版本号
VersionInfo=newWCHAR[uLen+1];
VersionInfo[uLen]='\0';
UINTtest=0;
while(test<=uLen)
{
VersionInfo[test]=VersionString->FileVersion[test]; //赋给VersionInfo;
test++;
}
delete[]Version;
return VersionInfo;
}
程序二:Download.exe
//Download.cpp : 定义控制台应用程序的入口点。
//
#include"stdafx.h"
boolStartDownloadNewVersion();
bool StartSetup();
DWORD WINAPIShowrate(LPVOID lpParam);
DWORDfilesize;
float total=0.0;
float downloaddone=1;
floatrate=0.0;
int_tmain(int argc, _TCHAR* argv[])
{
HANDLE Hshow;
DWORDdwThread;
if(::MessageBox(NULL,_T("下载新版本,按确定继续"),_T("提示"),MB_OKCANCEL)==IDOK)
{
Hshow=CreateThread( //做了一个简单显示下载进度的显示;
NULL,
0,
Showrate, //显示进度函数;
NULL,
0,
&dwThread);
if(Hshow)
{
if(StartDownloadNewVersion()) //从指定的服务器上下载新的文件,这里是一个安装文件.msi
{
cout<<"100%Download the new version havedown"<<endl;
MessageBox(NULL,_T("下载成功,进行安装"),_T("成功"),MB_OK);
StartSetup(); //启动安装程序。当然在相应的盘符下得有这个setup.exe程序,
}
else
{
cout<<"Downloadthe version error"<<endl;
return0;
}
}
return0;
}
return 0;
}
boolStartDownloadNewVersion()
{
char Buff[1024]={0};
WCHAR*File=_T("D:\\READDER.msi");
LPCWSTRversionaddress=_T("http://localhost/webservice/READER.msi"); //模拟发布在本机;
DWORDdwRead,dwWrite;
HINTERNET hInet=NULL,hfile=NULL;
HANDLEHandfile=NULL;
hInet=InternetOpen(
_T("Test"),
INTERNET_OPEN_TYPE_DIRECT,
NULL,
NULL,
0);
if(hInet)
{
hfile=InternetOpenUrl(hInet,versionaddress,NULL,0,0,0);
if(hfile)
{
Handfile=CreateFile( //在指定文件夹中创建改文件名;
File,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(Handfile)
{
InternetQueryDataAvailable(hfile,&filesize,0,0); //预先得到将要下载的文件的大小,为显示进度做准备用;
total=filesize/1024;
do{
InternetReadFile(hfile,Buff,1024,&dwRead); //从网络上读取文件,每次读1k
if(dwRead)
{
downloaddone++;
WriteFile(Handfile,Buff,dwRead,&dwWrite,NULL); //写入到创建的文件中;
rate=downloaddone/total;
Sleep(1); //延时,为了好观察,也防止CPU100%
}
}while(dwRead!=0); //下载完毕;
}
}
}
else
{
InternetCloseHandle(hfile); //扫尾工作
InternetCloseHandle(hInet);
CloseHandle(Handfile);
returnfalse;
}
InternetCloseHandle(hfile);
InternetCloseHandle(hInet);
CloseHandle(Handfile);
returntrue;
}
DWORDWINAPI Showrate(LPVOIDlpParam)
{
cout.precision(4); //设置为显示小数点后后4位;
while(1)
{
if(rate>1.00)
break; //退出;
cout<<rate*100<<"%";
system("cls"); //清屏;
}
return0;
}
bool StartSetup()
{
STARTUPINFOsi;
PROCESS_INFORMATIONpi;
ZeroMemory(&si,sizeof(si));
si.cb=sizeof(si);
si.wShowWindow=SW_SHOWNORMAL;
ZeroMemory(&pi,sizeof(pi));
if(!CreateProcess(
_T("c:\\setup.exe"), //程序的安装程序
NULL,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&si,
&pi)
)
{
cout<<"CreateProcessfailed"<<GetLastError()<<endl;
returnfalse;
}
exit(1);
}