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

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

阅读更多

最近单位开发一个项目,其中需要用到自动升级功能。因为自动升级是一个比较常用的功能,可能会在很多程序中用到,于是,我就想写一个自动升级的组件,在应用程序中,只需要引用这个自动升级组件,并添加少量代码,即可实现自动升级功能。因为我们的程序中可能包含多个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# 智能升级程序 完整源码

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

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

    1. 客户端(通常是PC上的C#应用程序)连接到设备的串口。 2. 应用程序通过Ymodem协议打包固件文件,准备好发送。 3. 设备接收到文件传输请求后,启动IAP模式,准备接收和验证固件数据。 4. 数据包逐个传输,如果发生...

    c# 升级程序

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

    智能交通查询系统 c#

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

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

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

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

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

    C#车牌识别抓拍DEMO

    1. **C#编程基础**:C#是一种面向对象的编程语言,由微软公司开发,广泛用于Windows平台的软件开发。在本DEMO中,C#作为核心开发语言,负责程序的逻辑控制、数据处理和界面交互。 2. **图像处理库**:C#中常见的...

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

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

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

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

    FAUNC FOCAS C#示例

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

    C#_MySQL_智能炼铁项目.zip

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

    qupdate自动升级 程序

    "qupdate自动升级程序"是一个专用于C/S(客户端/服务器)架构的软件更新解决方案。这个工具结合了qudate软件和一个C#编写的示例应用,旨在帮助开发者实现对软件文件的智能管理和更新,无论是自动还是手动,都能根据...

    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

    1. **C#**: C#是一种面向对象的编程语言,由微软公司开发,广泛应用于Windows平台的软件开发。在这个项目中,C#作为主要编程语言,负责实现系统的逻辑控制、用户界面交互以及与硬件设备的通信。 2. **人工智能 (AI)...

Global site tag (gtag.js) - Google Analytics