最近单位开发一个项目,其中需要用到自动升级功能。因为自动升级是一个比较常用的功能,可能会在很多程序中用到,于是,我就想写一个自动升级的组件,在应用程序中,只需要引用这个自动升级组件,并添加少量代码,即可实现自动升级功能。因为我们的程序中可能包含多个exe或者dll文件,所以要支持多文件的更新。

首先,要确定程序应该去哪里下载需要升级的文件。我选择了到指定的网站上去下载,这样比较简单,也通用一些。在这个网站上,需要放置一个当前描述最新文件列表的文件,我们估且叫它服务器配置文件。这个文件保存了当前最新文件的版本号(lastver),大小(size),下载地址(url),本地文件的保存路径(path),还有当更新了这个文件后,程序是否需要重新启动(needRestart)。这个文件大致如下:
updateservice.xml
<?xml version="1.0" encoding="utf-8"?>
<updateFiles>
<file path="AutoUpdater.dll" url="http://update.iyond.com/CompanyClientApplication/AutoUpdater.zip" lastver="1.0.0.0" size="28672" needRestart="true" />
<file path="CompanyClient.exe" url="http://update.iyond.com/CompanyClientApplication/CompanyClient.zip" lastver="1.1.0.0" size="888832 " needRestart="true" />
<file path="HappyFenClient.dll" url="http://update.iyond.com/CompanyClientApplication/HappyFenClient.zip" lastver="1.0.0.0" size="24576" needRestart="true" />
<file path="NetworkProvider.dll" url="http://update.iyond.com/CompanyClientApplication/NetworkProvider.zip" lastver="1.0.0.0" size="32768" needRestart="true" />
<file path="Utility.dll" url="http://update.iyond.com/CompanyClientApplication/Utility.zip" lastver="1.0.0.0" size="20480" needRestart="true" />
<file path="Wizard.dll" url="http://update.iyond.com/CompanyClientApplication/Wizard.zip" lastver="1.0.0.0" size="24576" needRestart="true" />
</updateFiles>

同时,客户端也保存了一个需要升级的本地文件的列表,形式和服务器配置文件差不多,我们叫它本地配置文件。其中,<Enable>节点表示是否启用自动升级功能,<ServerUrl>表示服务器配置文件的地址。
update.config
<?xml version="1.0" encoding="utf-8"?>
<Config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Enabled>true</Enabled>
<ServerUrl>http://update.iyond.com/updateservice.xml</ServerUrl>
<UpdateFileList>
    <LocalFile path="AutoUpdater.dll" lastver="1.0.0.0" size="28672" />
    <LocalFile path="CompanyClient.exe" lastver="1.1.0.0" size="888832 " />
    <LocalFile path="HappyFenClient.dll" lastver="1.0.0.0" size="24576" />
    <LocalFile path="NetworkProvider.dll" lastver="1.0.0.0" size="32768" />
    <LocalFile path="Utility.dll" lastver="1.0.0.0" size="20480" />
    <LocalFile path="Wizard.dll" lastver="1.0.0.0" size="24576" />
</UpdateFileList>
</Config>

使用自动各级组件的程序在启动时,会去检查这个配置文件。如果发现有配置文件中的文件版本和本地配置文件中描述的文件版本不一致,则提示用户下载。同时,如果本地配置文件中某些文件在服务器配置文件的文件列表中不存在,则说明这个文件已经不需要了,需要删除。最后,当升级完成后,会更新本地配置文件。

我们先来看一下如何使用这个组件。
在程序的Program.cs的Main函数中:

[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

AutoUpdater au = new AutoUpdater();
    try
    {
        au.Update();
    }
    catch (WebException exp)
    {
        MessageBox.Show(String.Format("无法找到指定资源\n\n{0}", exp.Message), "自动升级", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    catch (XmlException exp)
    {
        MessageBox.Show(String.Format("下载的升级文件有错误\n\n{0}", exp.Message), "自动升级", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    catch (NotSupportedException exp)
    {
        MessageBox.Show(String.Format("升级地址配置错误\n\n{0}", exp.Message), "自动升级", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    catch (ArgumentException exp)
    {
        MessageBox.Show(String.Format("下载的升级文件有错误\n\n{0}", exp.Message), "自动升级", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    catch (Exception exp)
    {
        MessageBox.Show(String.Format("升级过程中发生错误\n\n{0}", exp.Message), "自动升级", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }

Application.Run(new MainUI());
}

如上所示,只需要简单的几行代码,就可以实现自动升级功能了。

软件运行截图:

下面,我们来详细说一下这个自动升级组件的实现。
先看一下类图:

AutoUpdater:自动升级的管理类,负责整体的自动升级功能的实现。
Config:配置类,负责管理本地配置文件。
DownloadConfirm:一个对话框,向用户显示需要升级的文件的列表,并允许用户选择是否马上升级。
DownloadFileInfo:要下载的文件的信息
DownloadProgress:一个对话框,显示下载进度。
DownloadProgress.ExitCallBack,
DownloadProgress.SetProcessBarCallBack,
DownloadProgress.ShowCurrentDownloadFileNameCallBack:由于.NET2.0不允许在一个线程中访问另一个线程的对象,所以需要通过委托来实现。
LocalFile:表示本地配置文件中的一个文件
RemoteFile:表示服务器配置文件中的一个文件。
UpdateFileList:一个集合,从List<LocalFile>继承

我们先整体看一下AutoUpdater.cs:

public class AutoUpdater
{
    const string FILENAME = "update.config";
    private Config config = null;
    private bool bNeedRestart = false;

public AutoUpdater()
    {
        config = Config.LoadConfig(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, FILENAME));
    }
    /**/
    /// <summary>
    /// 检查新版本
    /// </summary>
    /// <exception cref="System.Net.WebException">无法找到指定资源</exception>
    /// <exception cref="System.NotSupportException">升级地址配置错误</exception>
    /// <exception cref="System.Xml.XmlException">下载的升级文件有错误</exception>
    /// <exception cref="System.ArgumentException">下载的升级文件有错误</exception>
    /// <exception cref="System.Excpetion">未知错误</exception>
    /// <returns></returns>
    public void Update()
    {
        if (!config.Enabled)
            return;
        /**/
        /*
     * 请求Web服务器,得到当前最新版本的文件列表,格式同本地的FileList.xml。
     * 与本地的FileList.xml比较,找到不同版本的文件
     * 生成一个更新文件列表,开始DownloadProgress
     * <UpdateFile>
     * <File path="" url="" lastver="" size=""></File>
     * </UpdateFile>
     * path为相对于应用程序根目录的相对目录位置,包括文件名
     */
        WebClient client = new WebClient();
        string strXml = client.DownloadString(config.ServerUrl);

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);
            }
        }
    }

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);
            }
        }
    }

private Dictionary<string, RemoteFile> ParseRemoteXml(string xml)
    {
        XmlDocument document = new XmlDocument();
        document.LoadXml(xml);

Dictionary<string, RemoteFile> list = new Dictionary<string, RemoteFile>();
        foreach (XmlNode node in document.DocumentElement.ChildNodes)
        {
            list.Add(node.Attributes["path"].Value, new RemoteFile(node));
        }

return list;
    }
    public event ShowHandler OnShow;
}

在构造函数中,我们先要加载配置文件:

public AutoUpdater()
{
    config = Config.LoadConfig(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, FILENAME));
}

c# 智能升级程序代码(1)相关推荐

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

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

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

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

  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. 【知识发现】基于用户的协同过滤推荐算法python实现
  2. hapi mysql项目实战路由初始化_用hapi.js mysql和nuxt.js(vue ssr)开发仿简书的博客项目...
  3. 运维祈求不宕机_[国庆特辑] 程序员应该求谁保佑才能保证不宕机?
  4. 中关村修电脑记实:那些年,修电脑犯下的错!
  5. 卸载/删除Homebrew包,包括其所有依赖项
  6. springboot 配置mybatis
  7. 重装系统数据恢复工具
  8. 2022-2027年中国认证检验检测行业市场全景评估及发展战略研究报告
  9. 【蓝桥杯Web】第十四届蓝桥杯(Web 应用开发)模拟赛 1 期-大学组 | 精品题解
  10. HC-05/06蓝牙模块的原理及使用方法
  11. python暑假培训班
  12. ConcurrentModificationException
  13. 数据中心管理常见错误,犯一个就是致命的
  14. 牛客网JavaScript V8在线编程输入输出
  15. Wargames学习笔记--Bandit
  16. 大一下Java大作业——双人联机小游戏森林冰火人
  17. oracle中ip带转数字,【PL/SQL】IP与数字互转
  18. 2022年最实用的DevOps工具
  19. CoffeeScript - CoffeeScript安装使用入门
  20. java font 字体库,「Font」- 编程字体 @20210209

热门文章

  1. 信息学奥赛一本通 2024:【例4.10】末两位数
  2. 信息学奥赛一本通(1175:除以13)
  3. 信息学奥数一本通(1004:字符三角形)
  4. Product of Three Numbers(CF-1294C)
  5. 信息学奥赛C++语言: 求小数的某一位
  6. 信息学奥赛一本通C++语言——1093:计算多项式的值
  7. 8 SAP QUERY定制报表操作手册 SQVI-推荐
  8. python内置类型方法_浅析Python数字类型和字符串类型的内置方法
  9. LaTeX:Texlive 2019和TeX studio
  10. 剖析Caffe源码之Layer_factory