cdo

可复用的自动升级系统实现

相对于B/S结构来说,C/S模式的客户端的部署和升级是一个很大的麻烦。有很多企业用户就是因为这个原因而放弃使用C/S。然而当一个应用必须要使用C/S结构才能很好的实现其功能的时候,我们该如何解决客户端的部署与自动升级问题了?

部署很简单,只要点击安装程序即可,难的在于每当有新版本发布时,能够实现自动升级。首先,我需要把自动升级的概念扩展一下。自动升级不仅仅是把当前版本的主程序EXE或其使用dll自动升级新的版本,还包括,当新版本的EXE需要使用原先不存在的dll时,自动升级系统也能够自动下载这些新的dll,再进一步,自动升级系统还能删除那些不再使用的dll。

我们的目标很简单,我们希望开发一个与具体应用无关的能够复用的自动升级系统,我将它称为UpdateActionSystem。

一般我们C/S的客户端有一个主应用程序EXE和一系列辅助的DLL组成,另外还可能包括必要的配置文件和其它资源文件,为了能实现所有这些文件的自动更新,我们引入UpdateActionSystem.exe和一个版本配置文件UpdateConfig.xml放在与主程序EXE相同的目录中。UpdateConfig.xml中有当前目录下所有文件的当前版本。那么UpdateActionSystem.exe从何处获取每个文件最新的版本号了?对,从数据库。UpdateConfig.xml中给出了该数据库的位置信息。先看看UpdateConfig.xml的内容。


<?xml version="1.0" encoding="gb2312"?>
<GTPDef xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance">
  <HostInfo>
    <DataBaseIP>218.201.34.117</DataBaseIP>
    <DataBaseName>haonet</DataBaseName>
    <SoftwareType>OASystem</SoftwareType>
    <CommonSoftwareTypeName>Common</CommonSoftwareTypeName>
  </HostInfo>
  <VersionInfo>
    <GoldPrinter.dll>2.000</GoldPrinter.dll>
    <XSkyControls.dll>1.000</XSkyControls.dll>
    <OASystem.exe>0.995</OASystem.exe>   
  </VersionInfo>
</GTPDef>

可以看到,在这个示例中,我的客户端系统有一个主程序OASystem.exe ,和两个dll--GoldPrinter.dll ,XSkyControls.dll,它们的版本号也记录于此。另外HostInfo部分记录了UpdateActionSystem.exe应该从何处获取最新版本号信息,其中的SoftwareType字段和CommonSoftwareTypeName字段在有多个不同的客户端系统都需要升级时会作为区别标志。

好,我们知道了可以从数据库中的SoftwareVersion表获取最新版本信息,我们可以看看这个表的结构:
SoftwareName -- 更新文件的名称。
URL -- 下载该文件的地址。
Version -- 该文件的最新版本号
SoftwareType -- 文件类型(与上面的配置文件中的对应)

所以当UpdateActionSystem.exe从数据库中获取的版本号必当前版本号要高,那么它就会从URL指示的地方下载新的文件。另外,如果UpdateActionSystem.exe发现数据库中的表中有一个文件的SoftwareType与配置文件中的值相同,而此文件的信息在配置文件中又不存在,说明这个文件是新加入的,于是UpdateActionSystem.exe就下载这个文件。

可以看出,我们基本把如何实现一个可复用的自动升级系统的思路已经清楚了,它是与应用无关的。
如果我们的一套系统需要引入自动升级,只需一下几个步骤:
(1)引入UpdateActionSystem.exe和一个版本配置文件UpdateConfig.xml放在与主程序EXE相同的目录中,并修改UpdateConfig.xml中的内容与当前应用一致。
(2)在数据库中增加SoftwareVersion表,并填入相应的文件信息记录。
(3)将以后新版本的文件放在数据库中URL指示的地方。
(4)在主程序中添加一个对自己的最新版本检查,如果发现有新版本,则启动UpdateActionSystem.exe。

(一般将主程序作为升级的触发器,这是以为主程序更新了,其它的dll文件可能没有更新,但是如果一个dll更新了,则主程序必定发生变化。当然你也可以直接点击UpdateActionSystem.exe进行更新。)

看看我的示例运行的图片。

当有新版本时,界面如下:

点击蓝色链接后,即执行UpdateActionSystem.exe,界面如下:

升级结束后,界面如下:

关于整个UpdateActionSystem.exe系统实现的源代码将在下期文章给出。




本文引用通告地址: http://blog.csdn.net/zhuweisky/services/trackbacks/415474.aspx

        上一篇文章解决了实现可复用的自动升级系统的思路,这篇文章将给出UpdateActionSystem.exe的参考实现及相关的牵涉主程序的代码。

UpdateActionSystem.exe的主窗体UpdatingForm的主要成员如下:

  private UpdateConfigParser updateParser = null ;//用于解析版本配置文件UpdateConfig.xml
  private DealSoftwareVersion dealVersion = null ;//用于访问数据库的SoftwareVersion表
  private string curApppath = null ; //当前路径

//构造函数中初始化各成员

#region ctor
  public UpdatingForm()
  {   
   InitializeComponent(); 
 
   this.curApppath = System.IO.Directory.GetParent(Application.ExecutablePath).ToString();  
   this.progressControl2.SetIDealEvent(this) ;

   this.updateParser = new UpdateConfigParser(this.curApppath + "\\UpdateConfig.xml") ;
   string connStr = ...... ;

   this.dealVersion = new DealSoftwareVersion(connStr) ;
  }
  #endregion

//下载新版本文件的线程:

#region DownloadThread
  private void DownloadThread()
  {
   int succeedCount = 0 ;
   int failCount = 0 ;

   
   SoftwareVersion[] versions = null ;

   try
   {    
    versions = (SoftwareVersion[])this.dealVersion.GetObjects("") ;
    if((versions == null) || (versions.Length == 0))
    {
     MessageBox.Show("没有任何文件需要升级!") ;
     this.Close() ;
    }
   }
   catch
   {
    MessageBox.Show("无法与数据库服务器建立连接,可能是服务器已关闭!升级失败!") ;
    this.Close() ;
   }

   for(int i=0 ;i<versions.Length ;i++)
   {
    if((versions[i].SoftwareType != this.updateParser.SoftwareType) && (versions[i].SoftwareType != this.updateParser.CommonSoftwareTypeName))
    {
     continue ;
    }

    string softName = versions[i].SoftwareName ;
    decimal newVer  = versions[i].Version ;
    string url      = versions[i].URL ;
    string filePath = this.curApppath + "\\" + softName ;

    bool isExit = this.updateParser.IsSoftwareExit(softName) ;
    if(isExit)
    {
     decimal oldVer = this.updateParser.GetSoftwareVersion(softName) ;

     if(oldVer < newVer) //覆盖旧文件
     {
      this.SetTitle(softName ,true) ;
      bool succeed = this.DownLoadOneFile(url ,filePath ,this.progressControl2) ;
      if(succeed)
      {
       this.updateParser.SetNewVersion(softName ,newVer) ;
       ++ succeedCount ;
       this.DisplayMsg(string.Format("成功升级{0}文件!" ,softName)) ;
      }
      else
      {
       ++ failCount ;
       this.DisplayMsg(string.Format("升级{0}文件失败!" ,softName)) ;
      }
     }
    }
    else //下载新文件
    {
     this.SetTitle(softName ,false) ;
     this.updateParser.AddNewSoftware(softName ,newVer) ;
     bool succeed = this.DownLoadOneFile(url ,filePath ,this.progressControl2) ;
      
     if(succeed)
     {
      ++ succeedCount ;
      this.DisplayMsg(string.Format("成功下载{0}文件!" ,softName)) ;
     }
     else
     {
      ++ failCount ;
      this.updateParser.SetNewVersion(softName ,0) ;
      this.DisplayMsg(string.Format("下载{0}文件失败!" ,softName)) ;
     }
    }    
   }
   
   string msg = null ;
   if(succeedCount+failCount == 0)
   {
    msg = "没有任何文件需要更新!" ;
   }
   else if((succeedCount > 0) && (failCount == 0))
   {
    msg = string.Format("成功更新{0}个文件!",succeedCount) ;
   }
   else
   {
    msg = string.Format("总共需要更新{0}个文件,成功更新{1}个文件!有{2}个文件更新失败!" , succeedCount+failCount ,succeedCount ,failCount) ;
   }

   MessageBox.Show(msg) ;

   this.Close() ;
  }  
  #endregion

//下载某个文件的方法

#region DownLoadOneFile
  private bool DownLoadOneFile(string url ,string filePath ,ProgressControl proControl)
  {
   FileStream fstream  = new FileStream(filePath ,FileMode.Create ,FileAccess.Write);
   WebRequest wRequest =  WebRequest.Create(url);

   try
   {    
    WebResponse wResponse = wRequest.GetResponse(); 
    int contentLength =(int)wResponse.ContentLength;    
            
    byte[] buffer = new byte[1024];
    int read_count = 0 ;
    int total_read_count = 0 ;
    bool complete = false;

    proControl.SetParas(0 ,contentLength ,buffer.Length) ;     
    
    while (!complete )
    {
     read_count = wResponse.GetResponseStream().Read(buffer,0,buffer.Length);
     
     if(read_count > 0)
     {      
      fstream.Write(buffer ,0 ,read_count) ;
      total_read_count += read_count ;
      if(total_read_count <= contentLength)
       proControl.step_forward() ;     
     } 
     else
     {
      complete = true ;
     }
    }
    
    fstream.Flush() ;
    return true ;
   }
   catch(Exception ee)
   {  
    ee = ee ;
    return false ;
   }
   finally
   {    
    fstream.Close() ;    
    wRequest = null;
   }

  }
  #endregion  

//在窗体加载时,启动下载线程

#region Form1_Load
  private void Form1_Load(object sender, System.EventArgs e)
  {
   System.Threading.Thread.Sleep(1000) ;
   ThreadDelegate thread = new ThreadDelegate(this.DownloadThread) ;
   thread.BeginInvoke(null ,false) ; //异步执行
  }
  #endregion

UpdateActionSystem.exe的主要实现代码就是这些,下面给出主应用程序中的相关代码:

在登录窗体的构造函数中:

   //检查自动更新
   bool needUpdate  = this.NeedToUpdate() ;  
   this.linkLabel_update.Visible = needUpdate ;
   this.button_logon.Enabled = (! needUpdate) ;

  //点击linkLabel_update将启动UpdateActionSystem.exe

private void linkLabel_update_LinkClicked(object sender, System.Windows.Forms.LinkLabel_updateClickedEventArgs e)
  {
   Process downprocess = new Process();
   string apppath = System.IO.Directory.GetParent(Application.ExecutablePath).ToString();
   downprocess.StartInfo.FileName = string.Format("{0}\\{1}" , apppath ,UpdateActionSystem.exe) ;
   downprocess.Start();
   this.DialogResult = DialogResult.Cancel;
   return;  
  }

好了,主要的实现代码都给出来了,如果你想获取UpdateActionSystem.exe的完整源程序,可以email向我索取!sky.zhuwei@163.com



本文引用通告地址: http://blog.csdn.net/zhuweisky/services/trackbacks/415487.aspx

posted on 2005-09-06 16:15 Cdo 阅读(1535) 评论(40)  编辑 收藏 网摘 所属分类: .NET

评论

#1楼 2007-10-11 23:06 小土豆2[未注册用户]

我需要自动升级的代码,希望您能发份给我
cchny@163.com
  回复  引用    

#2楼 2007-10-13 09:19 刘红彬[未注册用户]

我需要自动升级的代码,希望您能发份给我
hatelhb@163.com
  回复  引用    

#3楼 2007-10-16 14:21 oatch[未注册用户]

求自动升级的代码,希望您能发份给我 [oatch@sina.com]
  回复  引用    

#4楼 2007-11-02 17:52 lilin[未注册用户]

博主你好 我需要份自动升级的代码。希望你能发给我。谢谢!   回复  引用    

#5楼 2007-11-09 15:02 赌东道[未注册用户]

能不能给我份完整的代码啊   回复  引用    

#6楼 2007-12-11 16:15 lx[未注册用户]

你好,能给个完整的例子吗?想好研究一下!!!谢谢了   回复  引用    

#7楼 2008-01-12 18:30 乱舞飞雪[未注册用户]

你好,能不能给我一份呀!zhangxiaoke2008@126.com
非常感谢!
  回复  引用    

#8楼 2008-01-22 12:00 maomao4109[未注册用户]

我想想看看源码   回复  引用    

#9楼 2008-03-02 15:10 海勃yujinmu[未注册用户]

你好,能不能也给我一份呀!yujinmu@hb56.com
非常感谢!
  回复  引用    

#10楼 2008-04-04 11:23 jiu[未注册用户]

你好,能不能也给我一份呀!jiu@tom.com
非常感谢
  回复  引用    

#11楼 2008-04-17 14:06 wewe[未注册用户]

你好!能不能给我一份呢,谢谢!
caoweiran1@163.com
  回复  引用    

#12楼 2008-04-22 11:35 5889666[未注册用户]

我要一份,5889666@sina.com
  回复  引用    

#13楼 2008-04-27 11:26 yonghuazeng[未注册用户]

我要一份, 谢谢   回复  引用    

#14楼 2008-05-19 16:55 ala2test[未注册用户]

请发一份给我,谢谢
ala2test@gmail.com
  回复  引用    

#15楼 2008-05-22 11:45 gggaopengfei@163.com[未注册用户]

希望能给我一份,谢谢!gggaopengfei@163.com   回复  引用    

#16楼 2008-05-29 15:15 ssihc110@qq.com[未注册用户]

请发一份给我,谢谢~~~~
  回复  引用    

#17楼 2008-06-05 09:21 superwz[未注册用户]

发给我一份,谢谢了!   回复  引用    

#18楼 2008-06-20 21:39 河[未注册用户]

能不能给我一份呀! 我需要学习!谢谢拉 我邮箱 he5384123@126.com   回复  引用    

#19楼 2008-07-15 13:33 jesico[未注册用户]

申请一份 谢谢! jesico@sina.com   回复  引用    

#20楼 2008-08-26 22:14 Fjj[未注册用户]

老大,给我发一份,谢谢!!!fjj@dghdcrc.cn   回复  引用    

#21楼 2008-09-01 13:38 rabbitet[未注册用户]

老大,请给我也发一份学习一下吧,先谢谢了。   回复  引用    

#22楼 2008-09-03 15:53 huangss[未注册用户]

hsghxm@163.com
谢谢
  回复  引用    

#23楼 2008-09-05 18:10 BigLong      

谢谢给我也发一份,正需要。再次感谢!libiglong@163.com   回复  引用  查看    

#24楼 2008-09-12 10:12 yuji[未注册用户]

博主,能不能给我发一份,谢谢了!bai_yuji@163.com   回复  引用    

#25楼 2008-09-22 11:20 trueben      

博主,能不能给我发一份,谢谢了!
trueben9527@126.com
  回复  引用  查看    

#26楼 2008-10-23 17:39 lxlhcy[未注册用户]

楼主也给我发一份,谢谢,hcylxl@yahoo.com.cn   回复  引用    

#27楼 2008-11-23 09:44 yangjunzhu[未注册用户]

请发一份,yangjunzhu@sina.com,谢谢!   回复  引用    

#28楼 2008-11-24 17:54 Jerry Qian      

请发一份jciwolf@126.com   回复  引用  查看    

#29楼 2008-12-12 14:12 可里[未注册用户]

不错
请发一份
cfam@163.com
谢谢
  回复  引用    

#30楼 2009-01-06 12:37 ayong[未注册用户]

如果 UpdateActionSystem.exe 本身也需要升级呢?   回复  引用    

#31楼 2009-03-31 10:26 查明[未注册用户]

哥们,能否发份到我邮箱158068302@qq.com, 研究下 谢谢   回复  引用    

#32楼 2009-04-06 12:17 tonyshi[未注册用户]

大侠,请发份到我邮箱signo@sohu.com,先谢谢了!   回复  引用    

#33楼 2009-04-07 11:39 xueyingchao[未注册用户]

xueyingc@126.com 大哥也发我份啊   回复  引用    

#34楼 2009-04-14 15:45 无心雨云      

源码我也要,邮件发给你了
longhun2004@126.com
  回复  引用  查看    

#35楼 2009-05-03 16:00 kzccomputer[未注册用户]

你好,能发我一份完整的自动更新程序的代码吗,谢谢!   回复  引用    

#36楼 2009-06-13 17:36 Tony Mao      

请给我一份源码,好吗?谢谢!!!   回复  引用  查看    

#37楼 2009-06-22 17:40 yanqiu

你好,能发我一份自动更新程序的代码吗,谢谢! 736258162@qq.com   回复  引用    

#38楼 2009-07-03 12:44 hebert

你好,能发我一份自动更新程序的代码吗,谢谢! richs2008@163.com   回复  引用    




发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 231229




相关文章:

相关链接: