win32 自动更新的一种方案

PS:文章是从本人sina博客搬移过来:

win32 自动更新的一种方案

ps:此只是一个思路,上不了台面的哈;


因工作需要,需要做出一个自动更新的方案;主要是作为内部使用,因此需要考虑的因素并不多。YI给出了其使用C#做的一些方法,然后提示了我应该怎么去做自动更新。其实个人感觉自动更新大体的思路都是一样。画出思路丢在了工作笔记本上,然后又是其他的事耽搁了,而上头亦没有做出什么要求,汗,直到那天YI给我看他的年终报告,才知道YI把这事记上了,而我有没有主动去弄,汗,有点对不起YI,于是上午就狠狠的弄了下把方案演示做给了YI.给出个交代.......

   具体思路:程序启动时,开启一个线程AA线程用来读取运行程序的版本号,并获取更新地址上保存的版本信息,然后比较版本是否有更新,如果有更新,则提示用户是否选择更新。如果选择了更新,那么,开启预设定好的下载进程,关闭正在运行的程序(好的更新程序会保存当前的工作,或者保存当前工作的配置等,更新完毕后悔重新启动原有程序,在此只是做一个方案,不要求有如此高的功能),下载完成后,覆盖原有的文件,启动安装进程。当然这是一种不规范的方法。仅供参考;贴上程序;程序一:模拟主函数运行,线程检测版本信息。程序二:下载存放在服务器上已更新的文件,覆盖原有文件,重新安装;

    程序一:
#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);
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值