最主要的就是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# 智能升级程序代码(2)相关推荐

  1. c# 智能升级程序代码

    最近单位开发一个项目,其中需要用到自动升级功能.因为自动升级是一个比较常用的功能,可能会在很多程序中用到,于是,我就想写一个自动升级的组件,在应用程序中,只需要引用这个自动升级组件,并添加少量代码,即 ...

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

    最近单位开发一个项目,其中需要用到自动升级功能.因为自动升级是一个比较常用的功能,可能会在很多程序中用到,于是,我就想写一个自动升级的组件,在应用程序中,只需要引用这个自动升级组件,并添加少量代码,即 ...

  3. 最近做的智能垃圾桶程序代码(1)

    /deng 2 #include //包含单片机寄存器的头文件 #include #include "Bit_Port.h" #include "key.h" ...

  4. 开源50万行代码,百亿广告分成,百度智能小程序能成吗?

    作者 | 非主流 出品 | AI科技大本营 终于,BAT 在小程序的赛道上展开了激战,而这一场战争得到了百度前所未有的重视. 9 月 4 日,百度总裁张亚勤称拉动百度业务的"新四小龙&quo ...

  5. matlab中存档算法代码,MATLAB 智能算法超级学习手册中程序代码

    [实例简介] MATLAB 智能算法超级学习手册中程序代码 [实例截图] [核心代码] dc90ef43-7920-434e-bdb8-0636c31c0b44 └── MATLAB 智能算法超级学习 ...

  6. 智能窗帘传感器c语言程序,基于单片机的智能窗帘控制系统设计(附程序代码)

    基于单片机的智能窗帘控制系统设计(附程序代码)(论文18000字,程序代码) 摘要:二十一世纪初以来,科学技术不断发展,智能家居涌现于各家各户,人们越来越重视生活质量的提高.但是传统的手动开合窗帘耗时 ...

  7. STM32F103代码远程升级(三)基于YModem协议串口升级程序的实现

    文章目录 一.YModem协议简介 二.YModem的数据格式 1.起始帧的数据格式 2.数据帧的数据格式 3.结束帧的数据格式 4.文件传输过程 三.基于Ymodem协议串口升级程序的实现过程 1. ...

  8. 基于智能家居c语言程序代码,基于单片机的智能家居系统设计(附程序代码)

    基于单片机的智能家居系统设计(附程序代码)(任务书,开题报告,外文翻译,论文10000字) 摘要 基于近年来通信电子技术的高速发展,使得一些原来可望不可及的事关民生的技术变为可能,条件允许的情况下,人 ...

  9. c语言数字植物管理系统,基于AT89C52单片机的智能浇花系统(包含程序代码)

    内容简介: 基于AT89C52单片机的智能浇花系统,毕业论文,共50页,18022字,附程序代码.实物图等. 摘要 伴随着经济的快速发展,人们的物质生活水平得到了极大的提高,生活质量越来越为人们关注. ...

最新文章

  1. nstimer循环引用_NSTimer定时器进阶——详细介绍,循环引用分析与解决
  2. 《深入理解mybatis原理》 MyBatis的一级缓存实现详解 及使用注意事项
  3. 华人博士拿下ACM SIGSOFT杰出博士论文奖,师从北大谢涛教授
  4. linux问答学知识
  5. Mtk Android 打包解包*.img
  6. 西电计算机本科学费,陕西高校学费大比拼!你当年的学费现在涨了多少
  7. postgresql 编码_上万份编码测试,大数据统计反映了公司在招聘时倾向的技能是什么...
  8. 知识点1: 进度条随数据变化,并添加渐变样式
  9. 外部函数能修改闭包内的变量_Python函数式编程,Python闭包
  10. django界面上弹出bootstrap modal对话框,对话框中包含iframe并请求一个新的页面
  11. drill 数据库查询方式简单说明
  12. python面向对象使用方法_python面向对象之方法
  13. CTF-Web SQL注入
  14. 安卓逆向 | 某新闻类APP urlSign
  15. 程序员试用期被裁,只给半个月赔偿
  16. 安卓版本客户端2.1
  17. 云服务器ecs什么意思
  18. JS正则表达式匹配域名
  19. OSError: [Errno 22] Invalid argument: ‘C:\\Users\\0moyi0\\Desktop\\AD_kk.png‘
  20. test api mis

热门文章

  1. 信息学奥赛一本通(1214:八皇后)
  2. Firing(POJ-2987)
  3. 数列分段(信息学奥赛一本通-T1428)
  4. Multiple Gift(AtCoder-3731)
  5. Machine Learning(CF-940F)
  6. 谁拿了最多奖学金(洛谷-P1051)
  7. 2 PP配置-一般设置-为工厂分配工厂日历
  8. Squeeze Net
  9. 时序图如何表现分支_静态时序分析圣经翻译计划——第五章:延迟计算 (上)...
  10. c语言程序错误提示一个找不到,C语言编辑程序出现错误提示.doc