软件自动在线升级的原理

4 1 准备一个XML配置文件 名称为AutoUpdater xml,作用是作为一个升级用的模板,显示需要升级的信息。 Xml代码 收藏代码 <?xml v

4.1 准备一个XML配置文件

 名称为AutoUpdater.xml,作用是作为一个升级用的模板,显示需要升级的信息。 
Xml代码  收藏代码
<?xml version="1.0"?//xml版本号   
<AutoUpdater>   
<URLAddres URL="http://www.dahuagong.com/update"///升级文件所在服务器端的网址   
<UpdateInfo>   
<UpdateTime Date = "2005-02-02"///升级文件的更新日期   
<Version Num = "1.0.0.1"///升级文件的版本号   
</UpdateInfo>   
<UpdateFileList> //升级文件列表   
<UpdateFile FileName = "aa.txt"///共有三个文件需升级   
<UpdateFile FileName = "VB40.rar"/>   
<UpdateFile FileName = "VB4-1.CAB"/>   
</UpdateFileList>   
<RestartApp>   
<ReStart Allow = "Yes"///允许重新启动应用程序   
<AppName Name = "TIMS.exe"///启动的应用程序名   
</RestartApp>   
</AutoUpdater>   

  从以上XML文档中可以得知升级文档所在服务器端的地址、升级文档的更新日期、需要升级的文件列表,其中共有三个文件需升级:aa.txt、VB40.rar、VB4-1.CAB。以及是否允许重新启动应用程序和重新启动的应用程序名。 
从以上XML文档中可以得知升级文档所在服务器端的地址、升级文档的更新日期、需要升级的文件列表,其中共有三个文件需升级:aa.txt、VB40.rar、VB4-1.CAB。以及是否允许重新启动应用程序和重新启动的应用程序名。 

  4.2 获取客户端应用程序及服务器端升级程序的最近一次更新日期 

  通过GetTheLastUpdateTime()函数来实现。 

Java代码  收藏代码
private string GetTheLastUpdateTime(string Dir)   
{   
    string LastUpdateTime = "";   
    string AutoUpdaterFileName = Dir + @"\AutoUpdater.xml";   

    if(!File.Exists(AutoUpdaterFileName))   
        return LastUpdateTime;   

    //打开xml文件   
    FileStream myFile = new FileStream(AutoUpdaterFileName,FileMode.Open);   
    //xml文件阅读器   
    XmlTextReader xml = new XmlTextReader(myFile);   
    while(xml.Read())   
    {   
        if(xml.Name == "UpdateTime")   
        {   
            //获取升级文档的最后一次更新日期   
            LastUpdateTime = xml.GetAttribute("Date");   
            break;   
        }   
    }   

    xml.Close();   
    myFile.Close();   
    return LastUpdateTime;   
}   


  通过XmlTextReader打开XML文档,读取更新时间从而获取Date对应的值,即服务器端升级文件的最近一次更新时间。 

函数调用实现: 

Java代码  收藏代码
//获取客户端指定路径下的应用程序最近一次更新时间   
string thePreUpdateDate = GetTheLastUpdateTime(Application.StartupPath);   
Application.StartupPath指客户端应用程序所在的路径。   

//获得从服务器端已下载文档的最近一次更新日期   
string theLastsUpdateDate = GetTheLastUpdateTime(theFolder.FullName);   
theFolder.FullName指在升级文档下载到客户机上的临时文件夹所在的路径。   

  4.3 比较日期 

  客户端应用程序最近一次更新日期与服务器端升级程序的最近一次更新日期进行比较。 


Java代码  收藏代码
//获得已下载文档的最近一次更新日期   
string theLastsUpdateDate = GetTheLastUpdateTime(theFolder.FullName);   

if(thePreUpdateDate != "")   
{   
    //如果客户端将升级的应用程序的更新日期大于服务器端升级的应用程序的更新日期   
    if(Convert.ToDateTime(thePreUpdateDate)>=Convert.ToDateTime(theLastsUpdateDate))   
    {   
        MessageBox.Show("当前软件已经是最新的,无需更新!",  
            "系统提示",MessageBoxButtons.OK,MessageBoxIcon.Information);   
        this.Close();   
    }   
}   
this.labDownFile.Text = "下载更新文件";   
this.labFileName.Refresh();   
this.btnCancel.Enabled = true;   
this.progressBar.Position = 0;   
this.progressBarTotal.Position = 0;   
this.progressBarTotal.Refresh();   
this.progressBar.Refresh();   

//通过动态数组获取下载文件的列表   
ArrayList List = GetDownFileList(GetTheUpdateURL(),theFolder.FullName);   
string[] urls = new string[List.Count];   
List.CopyTo(urls, 0);   


  将客户端升级的应用程序的日期与服务器端下载的应用程序日期进行比较,如果前者大于后者,则不更新;如果前者小于后者,则通过动态数组获取下载文件的列表,开始下载文件。 

  通过BatchDownload()函数来实现。升级程序检测旧的主程序是否活动,若活动则关闭旧的主程序;删除旧的主程序,拷贝临时文件夹中的文件到相应的位置;检查主程序的状态,若状态为活动的,则启动新的主程序。 

Java代码  收藏代码
private void BatchDownload(object data)   
{   
    this.Invoke(this.activeStateChanger, new object[]{true, false});   
    try   
    {   
        DownloadInstructions instructions = (DownloadInstructions) data;   
        //批量下载   
        using(BatchDownloader bDL = new BatchDownloader())   
        {   
            bDL.CurrentProgressChanged +=   
                new DownloadProgressHandler(this.SingleProgressChanged);   
            bDL.StateChanged +=   
                new DownloadProgressHandler(this.StateChanged);   
            bDL.FileChanged +=   
                new DownloadProgressHandler(bDL_FileChanged);   
            bDL.TotalProgressChanged +=   
                new DownloadProgressHandler(bDL_TotalProgressChanged);   
            bDL.Download(instructions.URLs, instructions.Destination,   
                (ManualResetEvent) this.cancelEvent);   
        }   
    }   
    catch(Exception ex)   
    {   
        ShowErrorMessage(ex);   
    }   

    this.Invoke(this.activeStateChanger, new object[]{false, false});   
    this.labFileName.Text = "";   

    //更新程序   
    if(this._Update)   
    {   
        //关闭原有的应用程序   
        this.labDownFile.Text = "正在关闭程序....";   
        System.Diagnostics.Process[] proc=  
            System.Diagnostics.Process.GetProcessesByName("TIMS");   
        //关闭原有应用程序的所有进程   
        foreach(System.Diagnostics.Process pro in proc)   
        {   
            pro.Kill();   
        }   

        DirectoryInfo theFolder=new DirectoryInfo(Path.GetTempPath()+"JurassicUpdate");   

        if(theFolder.Exists)   
        {   
            foreach(FileInfo theFile in theFolder.GetFiles())   
            {   
                //如果临时文件夹下存在与应用程序所在目录下的文件同名的文件,  
                //则删除应用程序目录下的文件   
                if(File.Exists(Application.StartupPath +   
                    "\\"+Path.GetFileName(theFile.FullName)))   
                    File.Delete(Application.StartupPath + "\\"+  
                        Path.GetFileName(theFile.FullName));   
                //将临时文件夹的文件移到应用程序所在的目录下   
                File.Move(theFile.FullName,Application.StartupPath +   
                    \\"+Path.GetFileName(theFile.FullName));   
            }   
        }   

        //启动安装程序   
        this.labDownFile.Text = "正在启动程序....";   
        System.Diagnostics.Process.Start(Application.StartupPath + "\\" + "TIMS.exe");   
        this.Close();   
    }   
}   


   这段程序是实现在线升级的关键代码,步骤有点复杂:首先用Invoke方法同步调用状态改变进程,然后调用动态链接库中批量下载 (BatchDownloader.cs)类启动批量下载,接着判断原有的主应用程序有没有关闭,如果没关闭,则用Process.Kill()来关闭主 程序。接下来,判断临时文件夹下(即下载升级程序所在的目录)是否存在与应用程序所在目录下的文件同名的文件,如果存在同名文件,则删除应用程序目录下的 文件,然后将临时文件夹的文件移到应用程序所在的目录下。最后重新启动主应用程序。这样更新就完成了。

【转自】http://chanshui.iteye.com/blog/729320