zoukankan      html  css  js  c++  java
  • 编写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

     
  • 相关阅读:
    日期控件选择条件控制只能选择当前日期之前或当前日期之后
    记录一次ajax 429请求laravel api的错误
    如何配置Linux系统的IP地址?
    laravel 定时任务通过队列发送邮件
    ioutil.ReadFile 读取文件内容时为什么读取不到文件呢?open var2.go: no such file or directory
    swoole异步io操作
    PHP获取本周所有日期或者最近七天所有日期
    面试又给我问到MySQL索引,最全的一次整理
    Google资深工程师深度讲解Go语言基础语法(二)
    ps命令详解
  • 原文地址:https://www.cnblogs.com/sdlfx/p/1888207.html
Copyright © 2011-2022 走看看