使用 Http 在线自动升级程序

 

使用 Http 在线自动升级程序


作者:
余延斌


下载源代码


 开发背景
近几日一些程序老要修改点小毛病,为避免每次都通知程序使用者,便有想做一个在线自动升级的程序。在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 &paraArr);
该函数是将命令行参数分解并保存到 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);
       ...  
有关其它细节请参考源代码。

 作者信息
电子邮件:yybhz@126.com
作者主页:http://yyb.yeah.net/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
程序功能: 本程序是检查程序版本并提供HTTP方式在线更新的程序! 支持多个文件、不同目录更新。 windows环境通用。 使用: 1.把所有需要更新的文件名称和版本号信息添加到更新列表XML文件中,XML文件内容格式: <?xml version="1.0" encoding="gb2312"?> BPL\FORM.bpl 2012.6.4.0 main.exe 2012.6.5.0 注意: 1)与XML文件同一个目录的,文件名不要含目录信息。 2)没有版本号的文件,每次发布时,自己编一个不同的版本号填入XML. 3)XML文件清单信息,每次发布都应包含所有的程序文件。 4)更新列表XML文件与程序文件一同发布到IIS虚拟目录中(windows环境下的)。 2.手动直接执行UPDATE.EXE文件更新时, 需要把更新列表XML文件的URL地址写在文本配置文件CLIENTDB.LXH中。 内容格式如下: [UPDATE] XMLURL=HTTP://192.168.0.80/RELEASE/FILELISTS.XML 3.由主控程序调用时,调用代码格式如下: ShellAPI.ShellExecute(0, 'Open', 'UPDATE.EXE', PWideChar(Params), '',SW_SHOWNORMAL); 其中Params参数,字符串内容必须按顺序分别为: 更新列表XML文件的URL地址 + 主控程序文件名 + 个性程序标题, 共传入三个入口参数,每个参数之间用空格隔开。 可以不传参数,则默认用CLIENTDB.LXH配置文件中的XML URL地址; 可以只传1个参数,参数此时必须为XML URL地址; 如果传第2个参数,更新完毕会自动启动主控程序; 如果传第3个参数,则更新程序标题为第3个参数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值