`
pcajax
  • 浏览: 2161899 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

c# 智能升级程序代码(2)

阅读更多

最主要的就是Update()这个函数了。当程序调用au.Update时,首先检查当前是否开户了自动更新:
if (!config.Enabled)
    return;

如果启用了自动更新,就需要去下载服务器配置文件了:
WebClient client = new WebClient();
string strXml = client.DownloadString(config.ServerUrl);

然后,解析服务器配置文件到一个Dictionary中:

Dictionary<string, RemoteFile> listRemotFile = ParseRemoteXml(strXml);

接下来比较服务器配置文件和本地配置文件,找出需要下载的文件和本地需要删除的文件:

List<DownloadFileInfo> downloadList = new List<DownloadFileInfo>();
//某些文件不再需要了,删除
List<LocalFile> preDeleteFile = new List<LocalFile>();

foreach (LocalFile file in config.UpdateFileList)
{
    if (listRemotFile.ContainsKey(file.Path))
    {
        RemoteFile rf = listRemotFile[file.Path];
        if (rf.LastVer != file.LastVer)
        {
            downloadList.Add(new DownloadFileInfo(rf.Url, file.Path, rf.LastVer, rf.Size));
            file.LastVer = rf.LastVer;
            file.Size = rf.Size;

            if (rf.NeedRestart)
                bNeedRestart = true;
        }

        listRemotFile.Remove(file.Path);
    }
    else
    {
        preDeleteFile.Add(file);
    }
}

foreach (RemoteFile file in listRemotFile.Values)
{
    downloadList.Add(new DownloadFileInfo(file.Url, file.Path, file.LastVer, file.Size));
    config.UpdateFileList.Add(new LocalFile(file.Path, file.LastVer, file.Size));

    if (file.NeedRestart)
        bNeedRestart = true;
}

如果发现有需要下载的文件,则向用户显示这些文件,并提示其是否马上更新。如果用户选择了马上更新,则先删除本地不再需要的文件,然后开始下载更新文件。
if (downloadList.Count > 0)
{
    DownloadConfirm dc = new DownloadConfirm(downloadList);

    if (this.OnShow != null)
        this.OnShow();

    if (DialogResult.OK == dc.ShowDialog())
    {
        foreach (LocalFile file in preDeleteFile)
        {
            string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, file.Path);
            if (File.Exists(filePath))
                File.Delete(filePath);

            config.UpdateFileList.Remove(file);
        }

        StartDownload(downloadList);
    }
}

我们再来看一下StartDownload函数

private void StartDownload(List<DownloadFileInfo> downloadList)
{
    DownloadProgress dp = new DownloadProgress(downloadList);
    if (dp.ShowDialog() == DialogResult.OK)
    {
        //更新成功
        config.SaveConfig(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, FILENAME));

        if (bNeedRestart)
        {
            MessageBox.Show("程序需要重新启动才能应用更新,请点击确定重新启动程序。", "自动更新", MessageBoxButtons.OK, MessageBoxIcon.Information);
            Process.Start(Application.ExecutablePath);
            Environment.Exit(0);
        }
    }
}

在这个函数中,先调用DownloadProgress下载所有需要下载的文件,然后更新本地配置文件,最后,如果发现某些更新文件需要重新启动应用程序的话,会提示用户重新启动程序。

至此,AutoUpdater这个类的使命就完成了,其实,整个的升级过程也就完成了。(废话)。

最后,我们来看一下这个组件是如何下载更新文件的

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.IO;
using System.Diagnostics;

namespace Iyond.Utility
{
    public partial class DownloadProgress : Form
    {
        private bool isFinished = false;
        private List<DownloadFileInfo> downloadFileList = null;
        private ManualResetEvent evtDownload = null;
        private ManualResetEvent evtPerDonwload = null;
        private WebClient clientDownload = null;

        public DownloadProgress(List<DownloadFileInfo> downloadFileList)
        {
            InitializeComponent();

            this.downloadFileList = downloadFileList;
        }

        private void OnFormClosing(object sender, FormClosingEventArgs e)
        {
            if (!isFinished && DialogResult.No == MessageBox.Show("当前正在更新,是否取消?", "自动升级", MessageBoxButtons.YesNo, MessageBoxIcon.Question))
            {
                e.Cancel = true;
                return;
            }
            else
            {
                if (clientDownload != null)
                    clientDownload.CancelAsync();

                evtDownload.Set();
                evtPerDonwload.Set();
            }
        }

        private void OnFormLoad(object sender, EventArgs e)
        {
            evtDownload = new ManualResetEvent(true);
            evtDownload.Reset();
            Thread t = new Thread(new ThreadStart(ProcDownload));
            t.Name = "download";
            t.Start();
        }

        long total = 0;
        long nDownloadedTotal = 0;

        private void ProcDownload()
        {
            evtPerDonwload = new ManualResetEvent(false);

            foreach (DownloadFileInfo file in this.downloadFileList)
            {
                total += file.Size;
            }

            while (!evtDownload.WaitOne(0, false))
            {
                if (this.downloadFileList.Count == 0)
                    break;

                DownloadFileInfo file = this.downloadFileList[0];

                //Debug.WriteLine(String.Format("Start Download:{0}", file.FileName));

                this.ShowCurrentDownloadFileName(file.FileName);

                //下载
                clientDownload = new WebClient();

                clientDownload.DownloadProgressChanged += new DownloadProgressChangedEventHandler(OnDownloadProgressChanged);
                clientDownload.DownloadFileCompleted += new AsyncCompletedEventHandler(OnDownloadFileCompleted);

                evtPerDonwload.Reset();

                clientDownload.DownloadFileAsync(new Uri(file.DownloadUrl), Path.Combine(AppDomain.CurrentDomain.BaseDirectory, file.FileFullName + ".tmp"), file);

                //等待下载完成
                evtPerDonwload.WaitOne();

                clientDownload.Dispose();
                clientDownload = null;

                //移除已下载的文件
                this.downloadFileList.Remove(file);
            }

            //Debug.WriteLine("All Downloaded");

            if (this.downloadFileList.Count == 0)
                Exit(true);
            else
                Exit(false);

            evtDownload.Set();
        }

        void OnDownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
            DownloadFileInfo file = e.UserState as DownloadFileInfo;
            nDownloadedTotal += file.Size;
            this.SetProcessBar(0, (int)(nDownloadedTotal * 100 / total));
            //Debug.WriteLine(String.Format("Finish Download:{0}", file.FileName));
            //替换现有文件
            string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, file.FileFullName);
            if (File.Exists(filePath))
            {
                if (File.Exists(filePath + ".old"))
                    File.Delete(filePath + ".old");

                File.Move(filePath, filePath + ".old");
            }

            File.Move(filePath + ".tmp", filePath);
            //继续下载其它文件
            evtPerDonwload.Set();
        }

        void OnDownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            this.SetProcessBar(e.ProgressPercentage, (int)((nDownloadedTotal + e.BytesReceived) * 100 / total));
        }

        delegate void ShowCurrentDownloadFileNameCallBack(string name);
        private void ShowCurrentDownloadFileName(string name)
        {
            if (this.labelCurrentItem.InvokeRequired)
            {
                ShowCurrentDownloadFileNameCallBack cb = new ShowCurrentDownloadFileNameCallBack(ShowCurrentDownloadFileName);
                this.Invoke(cb, new object[] { name });
            }
            else
            {
                this.labelCurrentItem.Text = name;
            }
        }

        delegate void SetProcessBarCallBack(int current, int total);
        private void SetProcessBar(int current, int total)
        {
            if (this.progressBarCurrent.InvokeRequired)
            {
                SetProcessBarCallBack cb = new SetProcessBarCallBack(SetProcessBar);
                this.Invoke(cb, new object[] { current, total });
            }
            else
            {
                this.progressBarCurrent.Value = current;
                this.progressBarTotal.Value = total;
            }
        }

        delegate void ExitCallBack(bool success);
        private void Exit(bool success)
        {
            if (this.InvokeRequired)
            {
                ExitCallBack cb = new ExitCallBack(Exit);
                this.Invoke(cb, new object[] { success });
            }
            else
            {
                this.isFinished = success;
                this.DialogResult = success ? DialogResult.OK : DialogResult.Cancel;
                this.Close();
            }
        }

        private void OnCancel(object sender, EventArgs e)
        {
            evtDownload.Set();
            evtPerDonwload.Set();
        }
    }
}

在构造函数中,将要下载的文件列表传进来

public DownloadProgress(List<DownloadFileInfo> downloadFileList)
{
    InitializeComponent();

    this.downloadFileList = downloadFileList;
}

在Form的Load事件中,启动下载线程,开始下载。

private void OnFormLoad(object sender, EventArgs e)
{
    evtDownload = new ManualResetEvent(true);
    evtDownload.Reset();
    Thread t = new Thread(new ThreadStart(ProcDownload));
    t.Name = "download";
    t.Start();
}

下载线程没什么特殊的,使用了WebClient的异步下载文件函数DownloadFileAsync,并且注册了两个事件,分别负责下载进度显示和下载完成后的处理:
clientDownload.DownloadProgressChanged += new DownloadProgressChangedEventHandler(OnDownloadProgressChanged);
clientDownload.DownloadFileCompleted += new AsyncCompletedEventHandler(OnDownloadFileCompleted);

大家看一下就明白了。

private void ProcDownload()
{
    evtPerDonwload = new ManualResetEvent(false);

    foreach (DownloadFileInfo file in this.downloadFileList)
    {
        total += file.Size;
    }

    while (!evtDownload.WaitOne(0, false))
    {
        if (this.downloadFileList.Count == 0)
            break;

        DownloadFileInfo file = this.downloadFileList[0];

        //Debug.WriteLine(String.Format("Start Download:{0}", file.FileName));

        this.ShowCurrentDownloadFileName(file.FileName);

        //下载
        clientDownload = new WebClient();

        clientDownload.DownloadProgressChanged += new DownloadProgressChangedEventHandler(OnDownloadProgressChanged);
        clientDownload.DownloadFileCompleted += new AsyncCompletedEventHandler(OnDownloadFileCompleted);

        evtPerDonwload.Reset();

        clientDownload.DownloadFileAsync(new Uri(file.DownloadUrl), Path.Combine(AppDomain.CurrentDomain.BaseDirectory, file.FileFullName + ".tmp"), file);

        //等待下载完成
        evtPerDonwload.WaitOne();

        clientDownload.Dispose();
        clientDownload = null;

        //移除已下载的文件
        this.downloadFileList.Remove(file);
    }

    //Debug.WriteLine("All Downloaded");

    if (this.downloadFileList.Count == 0)
        Exit(true);
    else
        Exit(false);

    evtDownload.Set();
}

最后,在OnDownloadFileCompleted函数中进行最后的处理。包括备份原文件,替换现有文件等。
void OnDownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
    DownloadFileInfo file = e.UserState as DownloadFileInfo;
    nDownloadedTotal += file.Size;
    this.SetProcessBar(0, (int)(nDownloadedTotal * 100 / total));
    //Debug.WriteLine(String.Format("Finish Download:{0}", file.FileName));
    //替换现有文件
    string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, file.FileFullName);
    if (File.Exists(filePath))
    {
        if (File.Exists(filePath + ".old"))
            File.Delete(filePath + ".old");

        File.Move(filePath, filePath + ".old");
    }

    File.Move(filePath + ".tmp", filePath);
    //继续下载其它文件
    evtPerDonwload.Set();
}

其它的函数只是一些显示进度条和下载信息的,这里就不再详细介绍了。

分享到:
评论

相关推荐

    C# 智能升级程序 完整源码

    C#智能升级程序是开发软件应用时不可或缺的一部分,它允许应用程序自动检查并安装最新的更新,以保持软件的性能和安全性。下面将详细讲解C#语言实现智能升级程序的关键知识点。 1. **自动更新机制**:智能升级程序...

    C#实现Ymodem协议IAP下载升级

    在C#中实现Ymodem协议,意味着开发者可以编写代码来创建一个客户端,将文件通过串行端口发送到目标设备,以及一个服务器端,接收并处理来自客户端的文件传输请求。 In-Application Programming(IAP)是一种程序...

    c# 升级程序

    在IT行业中,C#是一种广泛使用的编程语言,尤其在开发Windows桌面应用、Web应用以及游戏等领域。本篇文章将深入探讨如何...通过实践和学习,开发者可以打造出满足用户需求的智能升级程序,提升软件的稳定性和用户体验。

    智能交通查询系统 c#

    智能交通查询系统是一款基于C#编程语言开发的应用程序,旨在为用户提供便捷的公共交通查询服务,尤其是公交线路查询。系统的核心功能包括详细查询、站点查询和路线查询,这三大功能覆盖了用户在日常出行中可能遇到的...

    C# WPF 实现简单的自动更新智能客户端

    在IT行业中,C# WPF(Windows Presentation Foundation)是一种用于构建桌面应用程序的强大框架,由Microsoft开发。本主题将深入探讨如何使用C# WPF来实现一个简单的自动更新功能,这对于保持智能客户端应用的最新...

    C#源程序 定时关机时间预约升级版

    在本项目“C#源程序 定时关机时间预约升级版”中,开发者通过C#实现了丰富的实用功能,包括定时关机、时间预约、运行检测以及到期提醒,为用户提供了更加智能的时间管理工具。 首先,让我们详细了解一下定时关机...

    C#车牌识别抓拍DEMO

    7. **日志记录与升级机制**:“UpgradeLog2.XML”和“UpgradeLog.XML”可能用于记录程序升级信息和运行日志,便于调试和故障排查。“Backup”和“_UpgradeReport_Files”目录可能是备份和升级报告文件,保证系统的...

    BMS.rar_BMS C#_BMS程序_BMS系统_电池管理_能量管理

    电池管理系统(Battery ...总的来说,这个BMS程序旨在通过C#实现对电池管理的高度智能化,为用户提供可靠的数据支持,保障电池的稳定运行和高效利用。对于电池系统的设计、维护和优化,这样的工具是不可或缺的。

    FAUNC FOCAS C#示例

    在描述中提到的“使用C# FOCAS 1、2开发数控机床程序”,意味着我们将探讨两个版本的FOCAS接口——FOCAS 1和FOCAS 2。FOCAS 1主要应用于早期的FAUNC数控系统,它提供了基础的通信功能,如读取和写入NC程序、监控状态...

    小区物业管理系统(c#源码)

    在小区物业管理系统中,C#的这些特点使得代码结构清晰,易于维护,同时也保证了系统的稳定性和安全性。 二、系统架构与数据库设计 该小区物业管理系统采用Visual C# 2005作为开发环境,搭配Access数据库进行数据...

    C#_MySQL_智能炼铁项目.zip

    项目中的“LTZNNEW-master”文件可能是项目源码或资源的主目录,其中可能包含了C#项目的源代码文件(如.cs)、MySQL的数据库配置文件(如.cnf)以及相关的资源文件(如图片、配置文件等)。开发者或使用者可以通过...

    qupdate自动升级 程序

    2. **API调用**:如何在C#代码中集成qupdate的API,触发更新检查和安装过程。 3. **事件处理**:在升级过程中可能遇到的事件,如下载进度、错误处理等,以及如何编写对应的回调函数。 4. **安全考虑**:如何确保升级...

    c# 仓库管理系统 c#

    在信息技术日新月异的今天,利用C#语言开发的仓库管理系统能有效提高工作效率,减少人为错误,实现库存管理的智能化。本文将深入探讨C#在构建仓库管理系统中的应用及其关键知识点。 1. C#语言基础 C#是微软公司推出...

    C# 5.0 in a Nutshell, 5th Edition

    C# 5.0是微软开发的面向对象的编程语言,它在C# 4.0的基础上进行了一系列重要升级。其中最显著的新特性是异步编程模型,通过`async`和`await`关键字的引入,使得编写非阻塞的异步代码变得更加简洁。异步编程对于处理...

    C#网络应用编程基础练习题与答案.doc

    C#的网络应用编程涵盖了多种类型的应用,包括但不限于控制台应用程序、Windows应用程序、水晶报表应用程序、ASP.NET Web应用程序、Web服务应用程序以及智能设备应用程序。这使得C#能够构建从桌面应用到分布式Web系统...

    c#编程的简历管理系统

    6. **可扩展性与维护**:C#的面向对象特性使得代码易于组织和维护,为系统的后续升级和功能扩展提供了可能。例如,未来可添加视频简历上传、在线面试预约等高级功能。 总结而言,这个C#编程的简历管理系统是现代...

    办公自动化管理系统c#语句

    2. .NET Framework:C#运行在.NET Framework之上,该框架提供了一整套类库,包括ASP.NET(用于Web应用程序)、Windows Forms(用于桌面应用程序)等,使得开发者能够快速构建功能丰富的应用。 3. ASP.NET:由于办公...

    智能评教系统(C#_ASP.NET)

    C#是一种面向对象的编程语言,通常与微软的.NET框架一起使用,而ASP.NET是.NET框架的一部分,专门用于构建Web应用程序。 在开发智能评教系统时,开发者可能使用了ASP.NET的Web Forms或MVC架构。Web Forms提供了事件...

    人工智能-项目实践-C#-用C#写的基于halcon开发包的模组贴合影像系统.zip

    2. **人工智能 (AI)**: 人工智能是计算机科学的一个分支,致力于使机器模仿人类的智能行为。在这个系统中,AI体现在图像处理和模式识别技术上,通过学习和理解图像数据,自动识别模组的贴合状态。 3. **Halcon**: ...

Global site tag (gtag.js) - Google Analytics