WEB开发网
开发学院软件开发VC 使用Http在线自动升级程序 阅读

使用Http在线自动升级程序

 2010-07-01 20:43:23 来源:WEB开发网   
核心提示:开发背景近几日一些程序老要修改点小毛病,为避免每次都通知程序使用者,使用Http在线自动升级程序,便有想做一个在线自动升级的程序,在VCKBase看到一个是使用 FTP 的,完成更新,关键代码部分如下:...CStdioFile csf;if( !csf.Open( str+".upg", CFil

开发背景

近几日一些程序老要修改点小毛病,为避免每次都通知程序使用者,便有想做一个在线自动升级的程序。在VCKBase看到一个是使用 FTP 的,想到 FTP 需要用户名密码,许多程序如KFW 防火墙都能监看到程序发送的数据包,为防止密码泄露,故自己选用Http来做更新。我的思路是用命令行传递程序名称、版本号和 Update.ini 配置文件的 URL。命令行用法如下:

update.exe 程序名 版本 版本文件URL
例如:
  update.exe VolleyMail 3.0 http://www.extice.com/update/update.ini

解析命令行参数的函数原型如下:

CUpdateApp::GetCmdLinePara(CStringArray ¶Arr);该函数是将命令行参数分解并保存到 paraArr 数据中。然后将命令行信息传递给主对话框类,代码如下:dlg.m_strSoft = arr.GetAt(0);
    dlg.m_strVersion = arr.GetAt(1);
    AfxParseURL( arr.GetAt(2),
          dwType,
          dlg.m_strServer,
          dlg.m_strIniPath,
          dlg.m_dwPort);
这是对话框的初始化,将软件版本号显示在 List 框中,如图一:m_cis.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT,5);
    m_pHttp=m_cis.GetHttpConnection( m_strServer,m_dwPort );
    m_lbProduct.AddString(m_strSoft+" "+m_strVersion);

图一

然后是查找可用的更新,先通过 ChttpFile 将 Update.INI 文件下载到系统临时目录下,然后调用 GetPrivateProfileString 读取网上最新的版本号以及要更新的文件,判断是否需要更新,部分代码:csf.Open( m_strTempDir+"\\update.ini",
        CFile::modeCreate|CFile::modeWrite|CFile::typeBinary );
    char buf[2048];
    int n;
    while( ( n=pFile->Read( buf,2048 ) ) > 0 )
           csf.Write(buf,n);
    char buf[128];
    ::GetPrivateProfileString( m_strSoft,
                 "VERSION",
                 "1.0",
                 buf,
                 sizeof(buf),
                 m_strTempDir+"\\update.ini");
    m_strNewVer=buf;
    if(atof( m_strVersion ) >= atof( buf ) ) //现有版本大于
    {
       m_strStatus = "您现在用的版本已是最新的!";
       UpdateData(FALSE);
       m_buOK.EnableWindow(FALSE);
       return;
    }
更新部分代码

先通过 CUpdateDlg::FindAppProcessID() 看要更新的程序是否在运行:DWORD CUpdateDlg::FindAppProcessID()
    {
    HANDLE handle=::CreateToolhelp32Snapshot(TH32CS_SNAPALL,0);
      PROCESSENTRY32 Info;
    Info.dwSize = sizeof(PROCESSENTRY32);
    if(::Process32First(handle,&Info))
    {
        do{
           CString ss=Info.szExeFile;
           if(!ss.CompareNoCase(m_strSoft+".exe"))
           {
              ::CloseHandle(handle);
              return Info.th32ProcessID;
           }
       }
       while(::Process32Next(handle,&Info));
         ::CloseHandle(handle);
    }
      return -1;
    }

该函数返回程序进程号,如果要更新的程序正在运行的话,提示人工退出否则用TerminateProcess 杀掉进程!下载的文件大小用:pFile->QueryInfo(HTTP_QUERY_CONTENT_LENGTH,str);取得。为防止下载一半网络出现故障,先将下载的文件加后缀名.upg,下载全部成功后替换掉原来在用的程序,完成更新。

关键代码部分如下:...

       CStdioFile csf;
       if( !csf.Open( str+".upg",
               CFile::modeCreate
              | CFile::modeWrite
              | CFile::typeBinary
              | CFile::shareDenyWrite ) )
       {//先为*.upg文件
           AfxMessageBox("写文件"+str +"错误!\n文件正在使用中,请先关闭程序!",
                  MB_ICONSTOP);
           pFile->Close();
           return FALSE;
       }

       char buf[2048];
       DWORD dwRead=0;
       while((n=pFile->Read(buf,sizeof(buf)))>0)
       {
           dwRead+=n;
           m_prog.SetPos(100*dwRead/dwLen);
           MSG msg;
           for(int i=0;i<10;i++)
           {
              if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
              {
                  TranslateMessage(&msg);
                  DispatchMessage(&msg);
              }
           }
           csf.Write(buf,n);
       }
       pFile->Close();
    ...
    if(::DeleteFile(str)){
       ::rename(str+".upg",str);
       m_strStatus=strFile+"完成更新!";
       UpdateData(FALSE);
    ... 
有关其它细节请参考源代码。

本文配套源码

Tags:使用 Http 在线

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接