ClickOnce DIY全自动更新下载升级的自我实现

    技术2022-05-11  77

    SmartClient 概念近来比较热,但在微软提出这个名词以前已经有大量的软件在这么做了,一方面是简化客户端的部署,一方面是提供自动升级的功能;对于传统的 WinForm 应用来讲,确实是可以降低维护成本的一个不错的解决方案;   微软在推出 SmartClient 概念时,推出了相关的 updater Application Block ,做的也蛮不错,但作者前段还是根据软件特性自己写了一个很简单的实现,大家也大概能了解一下原理: 笔者的简化版自动升级管理器只需要四步走: 1. 一个负责查找和下载新版本的本地类 2. 本地配置文件中(或在代码中硬编码?不太好吧),指向更新服务器的 URL3. 服务器上一个标识版本号和新文件 URL 的配置文件 4. 调用示例 1. 版本管理类 using System;using System.Collections.Generic;using System.Text;using System.Xml;using System.Net;using System.IO;using System.Windows.Forms;namespace Survey{    class VersionAgent    {        public static bool CheckNetwork()        {            HttpWebRequest request;            try            {                request = (HttpWebRequest)WebRequest.Create(Pub.GetSetting("UpdateUrl") );// 从本地配置文件获取的网络中配置文件的 URL                 request.Proxy = WebProxy.GetDefaultProxy();                request.GetResponse();// 如果可以获得响应,说明网络没问题             }            catch (Exception e)            {                Pub.logError(e);                return false;            }             return true;        }           public static bool CheckUpdate()        {             XmlDocument doc = loadXMLDocument(Pub.GetSetting("UpdateUrl"));            Sys.UpdateUrl = GetValue(doc, "DownloadURL").Trim();// 将来会用这个 URL 自动下载             Sys.UpdatePage = GetValue(doc, "DownloadPage").Trim();// 如自动下载失败,会提供到这个页面手工下载             string warningRate = GetValue(doc, "WarningRate").Trim();            float.TryParse(warningRate,out Sys.WarningRate);             string NetVersion = GetValue(doc, "Version").Trim(); Version LocalVersion=System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;             return new Version(NetVersion).CompareTo(new Version(LocalVersion))>0;// 大于 0 说明有新版本发布         }// 这个方法是载入网络配置文件,读取一些不想放在本地的配置参数,以及比较本地和网络版本号         public static bool GoUpdate()        {           return DownLoadFile(Sys.UpdateFile,Sys.UpdateUrl);                  }         public static string GetValue(XmlDocument doc, string Key)        {            string Value;            try            {                XmlElement elem = (XmlElement)doc.SelectSingleNode(@"/config/app/" + Key);// 读取配置文件可自行定义                 Value = elem == null ? "" : elem.GetAttribute("value");             }            catch            {                Value = "";            }            return Value;        }         public static XmlDocument loadXMLDocument(string FileNameOrUrl)        {            XmlDocument doc = null;            try            {                doc = new XmlDocument();                doc.Load( FileNameOrUrl);            }            catch (Exception e)            {                System.Windows.Forms.MessageBox.Show(e.Message);                Pub.logError(e);                doc = null;            }            return doc;        }           public static bool DownLoadFile(string FileName, string Url)        {            bool Value = false;            WebResponse response = null;            Stream stream = null;             try            {                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);                 response = request.GetResponse();                stream = response.GetResponseStream();                 if (!response.ContentType.ToLower().StartsWith("text/"))                {                    Value = SaveBinaryFile(response, FileName);                 }             }            catch (Exception e)            {               // System.Windows.Forms.MessageBox.Show(e.Message);                Pub.logError(e);             }            return Value;        }           private static bool SaveBinaryFile(WebResponse response, string FileName)        {            bool Value = true;            byte[] buffer = new byte[1024];             try            {                if (File.Exists(FileName))                    File.Delete(FileName);                Stream outStream = System.IO.File.Create(FileName);                Stream inStream = response.GetResponseStream();                 int l;                do                {                    l = inStream.Read(buffer, 0, buffer.Length);                    if (l > 0)                        outStream.Write(buffer, 0, l);                }                while (l > 0);                 outStream.Close();                inStream.Close();            }            catch (Exception e)            {                System.Windows.Forms.MessageBox.Show(e.Message);                Pub.logError(e);                 Value = false;            }            return Value;        }    }} 2. 本地配置文件可能如: <configuration>  <appSettings>    <add key="UpdateUrl" value="http://www.abc.com/download/release.xml" />  </appSettings></configuration> 3. 网络配置文件可能如: <config>  <app>    <Version value="1.1.9.2" />    <ReleaseDate value="2006-12-12" />    <DownloadPage value="http://www.abc.com/download/index.htm" />    <DownloadURL value="http://www.abc.com/download/update.exe" />   <WarningRate value="0.3" />  </app></config> 4. 调用示例 在认为合适的时机(比如说应用程序启动时),启动一个后台线程去工作:             Thread thread = new Thread(new ThreadStart(threadMethodUpdate));            thread.Start();           private void threadMethodUpdate()        {             if (VersionAgent.CheckNetwork())// 网络状况正常             {                if (VersionAgent.CheckUpdate())// 检查更新并获取网络参数                 {                    if (VersionAgent.GoUpdate())// 获取新版本(由于我的软件很小,所以在不提示用户的情况就进行了新版下载,如认为不妥,可通过 MessageBox 提示一下)                     {                        MessageBox.Show(" 检测到产品的更新版本 , 即将开始自动更新! ", " 版本升级 ", MessageBoxButtons.OK, MessageBoxIcon.Information);                        System.Diagnostics.Process.Start(Sys.UpdateFile);                        System.Environment.Exit(0);                    }                    else                    {                        MessageBox.Show(" 系统检测到更新版本,但自动下载失败,点击确定进行手动下载 ", " 版本升级 ", MessageBoxButtons.OK, MessageBoxIcon.Error);                        System.Diagnostics.Process.Start(Sys.UpdatePage);                        System.Environment.Exit(0);                    }                }            }            else// 也可以什么也不提示                 MessageBox.Show(" 无法连接到服务器进行自动升级! /n 请检查网络连接 " + Pub.GetSetting("UpdateUrl"), " 网络异常 ", MessageBoxButtons.OK, MessageBoxIcon.Warning);         }    

    最新回复(0)