• 编写WinForm自动更新程序


        可能有一两年没有更新博客了,并不是由于没时间,或是这段时间没有丝毫的技术心得,只是每次打开博客,却又感觉无从可写。或许是因为没得到锻炼,文笔功夫过
    低吧。所以决定从今天起,借写日志锻炼一下。文档啊,希望下次写的时候不会那么痛苦了。
     
           从《编写WinForm自动更新程序》开始。
           
           C/S架构的项目,客户端将不可避免的面临自动更新问题,特别是在客户端数量较多时,自动更新显得尤为重要。据我所了解,WinForm程序自动更新有两种方案:
           1、使用ClickOnce发布客户端;
           2、自己编写自动更新程序;
      
           鉴于“偷懒”的原则,我试验了一下ClickOnce部署,在经过一番周折后终究是成功了,但感觉还是有几个缺点:
                 A、发布不方便。发布一次要生成程序清单、部属清单,生成的文件一不小心就完全不能用,又得重来,还有个似乎没什么用的.deploy;
                 B、无法指定程序安装目录。没去找过自动定位的安装目录,料想应该是隐藏得挺深的;
                 C、更新时无进度展示。这是比较影响用户体验的,若是更新失败,产生的日志连做开发的也未必知道所以然;
           还有个小缺点,在浏览器上启动安装,总觉得有点怪异。。。。
     
           于是乎,开始鼓捣一个自动更新程序。在设计过程中有几个问题必须做出选择:
     
           1、使用什么方式访问更新源?可以通过开发文件读取服务来提供更新源,可以使用FTP作为更新源,可以使用文件共享,可以使用WEB共享,等等。在此我选择了
    使用FTP作为更新源;
           2、根据什么来判断文件是否需要更新?首先想到的可能是版本号,但除DLL、EXE文件之外,大部分文件是没有版本号的,内容对比?那更不可取了。我使用了文
    件的HASH码来比较。每一个文件都可生成一个唯一的HASH码,只要该文件做过任何改动,生成的HASH码都将不一样。
     
           程序大致思路:提供一个独立的DLL供主程序调用,传入FTP访问凭据,启动更新程序并将主程序关闭,更新程序首先从FTP上下载一个文件清单,该文件清单中列
    举出了新版本中所有文件及目录,并保存了各文件的HASH。下载之后依次与本地文件的HASH对比,若发现不同,则下载文件并更新。遍历完成之后,启动主程序并附
    加参数通知调用的DLL已完成了更新,防止死循环,最后退出更新程序。下面说几个技术点:
     
           文件HASH码生成
            
        public static string GetMD5(Stream stream)
        {
            byte[] buffer;
            using (HashAlgorithm hash = HashAlgorithm.Create())
            {
                buffer = hash.ComputeHash(stream);
                hash.Clear();
            }
            return Convert.ToBase64String(buffer);
        }

           HashAlgorithm类是.NET框架中提供的,在System.Security.Cryptography命名空间下。这里发生了一件我不太理解的事:使用File.IsExist判断文件是否存在

    时,若传递的文件名参数前面多加了“\”,返回结果始终为true,不管文件是否真的存在,如File.IsExist(@”\temp\temp.xml”),更离奇的是,居然可以使用这个路径来生成HASH码。

         

           应用程序间传递参数

           在写控制台程序的时候,自动生成的Main方法中有参数string[] args,这便是传参入口。另外,可以使用Process类启动应用程序,例如:

        Process.Start(Application.StartupPath + "\\Update.exe", arguments);

           其中arguments是一个字符串,传递多个参数时,参数之间使用空格隔开。若单个参数内部有空格,请将该参数使用双引号括起。传递参数时注意“\”有可能会与

    紧随其后的字符组成形成转义,若是在Main中获取参数时发现参数个数不对,那就应该检查一下这个了。

           剩下的似乎就没什么说的了,都是些体力活。至于FTP的访问,用了一个以前一个朋友提供的类,本人也未曾研究其细节。展示更新进度时记得使用Form.Invoke来

    更新窗体呈现。

           使用这个自动更新程序时,首先使用Release项目来生成项目文件清单,然后将项目文件清单与生成的FileList.xml文件一并放在某个FTP目录下,配置好访问的用户

    名、密码后,在主程序中使用下列语句即可实现自动更新:

          FtpInfo ftpInfo = new FtpInfo("10software.gicp.net", "\\test", "ftpclient", "p@ssw0rd", 21);

          lib.Update.Pipe.Update(ftpInfo, UpdateBaseMode.ByFileHash);

           FTP是在Server2008下配置的,配置过程中遇到了些小麻烦,但终究是成功了。下一篇将简单介绍些Server2008下的FTP配置。

           程序源码:Updater.rar

     
  • 相关阅读:
    C#学习笔记-代理模式
    SqlDbx连接oracle
    C# 连接oracle,用32位client和64位Client,可能导致结果不同
    PHP&Java 调用C#的WCF
    DevExpress GridControl 控件二表连动
    SSAS 非重复计数
    Corn 表达式
    C# 实现Tree,包含parentId和children
    jsfiddle.net上的记录
    【慕课网实战】Spark Streaming实时流处理项目实战笔记十二之铭文升级版
  • 原文地址:https://www.cnblogs.com/sdlfx/p/1888207.html
Copyright © 2020-2023  润新知