版本更新基本操作

1.简介

  本文是制作了对软件进行自动更新的程序,有三个模式:

1、模式1
程序运行时:检查到更新,先偷偷下载,下载完成后,提示更新,手动点进行更新。开机启动时,若有完整的更新包,就进行直接更新。


2、模式2
程序运行时:检查到更新,提示更新,点击更新后,进行下载,下载完成后进行更新。开机启动时,若有完整的更新包,就进行直接更新。

 

3、模式3
程序运行时:不检查更新开机启动时,检查更新,下载更新,进行更新。

 

2.功能分析

  1)首先,设计了一个简单的客户端Web程序,使用Wcf进行数据传输,使客户端能够通过Wcf获取项目的版本信息和更新包下载地址。

  2)设计一个客户端,在这个客户端里面,我只是随意设计了一个窗口,然后在配置文件里面写明这个客户端的详细信息。

  3)最重要的来了,更新程序,先介绍一下必要的文件夹

  

  上面四个标注的文件是写死的了,必须存在的,这四个文件也就是客户端的全部内容了,ReayProject只是我存放开发文件的文件夹,部署用不到的。

  思路:更新时下载文件更新包在临时版本库,解压,把本地版本备份到备份版本,再把临时版本库的内容同步到本地版本,完成版本更新。

  在开始写各个更新功能之前,我们先写一下需要用到什么通用的功能,所以就写了一个基础操作类,供各个更新模式调用

  BasicOperation

using Ionic.Zip;
using Microsoft.Win32;
using System;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Xml;

namespace UpdateProgram
{
    /// <summary>
    /// 基础操作类
    /// </summary>
    class BasicOperation
    {
        /// <summary>
        /// 获取更新信息
        /// </summary>
        /// <param name="deploy"></param>
        /// <returns></returns>
        public virtual bool GetUpdateInfo(ref DeployModel deploy)
        {
            try
            {
                WcfPosService.PosWcfClient client = new WcfPosService.PosWcfClient();
                string retu = client.GetProjectVersion(deploy.ProjectName);
                if (retu != null)
                {
                    string[] retuArray = retu.Split(',');
                    deploy.NewVersion = Convert.ToDouble(retuArray[0].TrimStart('V'));
                    deploy.UpdateUrl = retuArray[1];
                    string[] vs = deploy.UpdateUrl.Split('/');
                    deploy.UpdateFileName = vs[vs.Length - 1];
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 关闭指定名字的服务
        /// </summary>
        /// <param name="ProcessName"></param>
        public void KillProcess(string ProcessName)
        {
            try
            {
                Process[] processes = Process.GetProcessesByName(ProcessName);
                foreach (Process p in processes)
                {
                    p.Kill();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 开启指定地址的服务
        /// </summary>
        /// <param name="ProcessPath"></param>
        public void StartProcess(string ProcessPath)
        {
            try
            {
                Process p = new Process();
                p.StartInfo.FileName = ProcessPath;
                p.Start();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 根据Url返回网络文件数据流
        /// </summary>
        /// <param name="Url"></param>
        /// <returns></returns>
        public Stream GetUrlStream(string Url)
        {
            try
            {
                HttpWebRequest request = WebRequest.Create(Url) as HttpWebRequest;
                HttpWebResponse response = request.GetResponse() as HttpWebResponse;
                Stream responseStream = response.GetResponseStream();
                return responseStream;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 带Range根据Url返回网络文件数据流
        /// </summary>
        /// <param name="Url"></param>
        /// <param name="Range">断点续传</param>
        /// <returns></returns>
        public Stream GetUrlStreamAddRange(string Url, long Range)
        {
            try
            {
                HttpWebRequest request = WebRequest.Create(Url) as HttpWebRequest;
                request.AddRange((int)Range);
                HttpWebResponse response = request.GetResponse() as HttpWebResponse;
                Stream responseStream = response.GetResponseStream();
                return responseStream;
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }
        /// <summary>
        /// 获取网络文件大小
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public long GetUrlFileLength(string Url)
        {
            try
            {
                return WebRequest.Create(Url).GetResponse().ContentLength;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 获取本地文件大小
        /// </summary>
        /// <param name="localFilePath"></param>
        /// <returns></returns>
        public long GetlStartPos(string localFilePath)//判断断点
        {
            try
            {
                return new FileInfo(localFilePath).Length;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 获取本地安装的WinRar的路径,若未安装,返回null
        /// </summary>
        /// <returns></returns>
        public string GetWinRarInstallPath()
        {
            string result = string.Empty;
            RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\WinRAR.exe");
            if (registryKey != null)
            {
                result = registryKey.GetValue("").ToString();
            }
            registryKey.Close();
            return result;
        }
        /// <summary>
        /// 解压Rar文件,需要先安装WinRar
        /// </summary>
        /// <param name="CompressFileUrl">需要解压的压缩文件</param>
        /// <param name="DecompressToDir">解压到哪个文件夹</param>
        /// <param name="WinRarPath">WinRarPath的安装目录</param>
        /// <returns>解压结果,成功为true,失败为false</returns>
        public bool DecompressFile(string CompressFileUrl, string DecompressToDir, string WinRarPath)
        {
            try
            {
                String commandOptions = string.Format("x {0} {1} -y", CompressFileUrl, DecompressToDir);
                string winrarDir = Path.GetDirectoryName(WinRarPath);
                ProcessStartInfo processStartInfo = new ProcessStartInfo();
                processStartInfo.FileName = Path.Combine(winrarDir, "rar.exe");
                processStartInfo.Arguments = commandOptions;
                processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                Process process = new Process();
                process.StartInfo = processStartInfo;
                process.Start();
                process.WaitForExit();
                process.Close();
                return true;
            }
            catch
            {
                return false;
            }
        }
        /// <summary>
        /// 解压Zip文件,不会报错
        /// </summary>
        /// <param name="CompressFileUrl">Zip文件地址</param>
        /// <param name="DecompressToDir">解压到此文件夹,若无,自动生成</param>
        public void DecompressZipFile(string CompressFileUrl, string DecompressToDir)
        {
            using (ZipFile zip = new ZipFile(CompressFileUrl, Encoding.UTF8))
            {
                zip.ExtractAll(DecompressToDir, ExtractExistingFileAction.OverwriteSilently);
            }
        }
        /// <summary>
        /// 删除指定文件夹下面的Rar和Zip压缩包
        /// </summary>
        /// <param name="Dir"></param>
        public void DeleteCompressBag(string Dir)
        {
            DirectoryInfo dir = new DirectoryInfo(Dir);
            foreach (FileInfo fi in dir.GetFiles("*.rar"))
            {
                fi.Delete();
            }
            foreach (FileInfo fi in dir.GetFiles("*.zip"))
            {
                fi.Delete();
            }
        }
        /// <summary>
        /// 同步文件夹里面的内容
        /// </summary>
        /// <param name="src">源地址</param>
        /// <param name="obj">目标地址</param>
        /// <param name="Complete">完全同步,true表示obj与src完全一致,false表示obj只根据src的内容进行添加和修改</param>
        public void RecursiveFile(string src, string obj, bool Complete = false)
        {
            DirectoryInfo dirSrc;
            if (Complete)
            {
                //没实现
                //dirSrc = new DirectoryInfo(obj);
                //FileSystemInfo[] FileSystemInfos = dirSrc.GetFileSystemInfos();
                //foreach (DirectoryInfo dir in FileSystemInfos)
                //{
                //    File.Delete(dir.Name);//清空所有
                //}
            }
            dirSrc = new DirectoryInfo(src);
            FileInfo[] fileInfos = dirSrc.GetFiles();
            foreach (FileInfo fi in fileInfos)//同步文件
            {
                string strsrc = src + "\\" + fi.Name;
                string strobj = obj + "\\" + fi.Name;
                if (File.Exists(strobj) == false)
                {
                    File.Copy(strsrc, strobj, true);
                    continue;
                }
                //比较两个文件的MD5码
                FileStream srcStream = new FileStream(strsrc, FileMode.Open);
                FileStream objStream = new FileStream(strobj, FileMode.Open);
                MD5 md5 = new MD5CryptoServiceProvider();
                byte[] srcVal = md5.ComputeHash(srcStream);
                byte[] objVal = md5.ComputeHash(objStream);
                srcStream.Close();
                objStream.Close();
                if (byteEquals(srcVal, objVal))
                {
                    continue;
                }
                File.Copy(strsrc, strobj, true);
            }
            DirectoryInfo[] dirSrcs = dirSrc.GetDirectories();
            foreach (DirectoryInfo dir in dirSrcs)//查找子目录
            {
                string strsrc = src + "\\" + dir.Name;
                string strobj = obj + "\\" + dir.Name;
                if (Directory.Exists(strobj) == false)
                {
                    Directory.CreateDirectory(strobj);
                }
                RecursiveFile(strsrc, strobj, false);
            }
        }
        /// <summary>
        /// 比较两个字节数组是否相同
        /// </summary>
        /// <param name="b1"></param>
        /// <param name="b2"></param>
        /// <returns></returns>
        public bool byteEquals(byte[] b1, byte[] b2)
        {
            for (int i = 0; i < b1.Length; i++)
                if (b1[i] != b2[i])
                    return false;
            return true;
        }
        /// <summary>
        /// 获取指定config文件中appSettings节点下key的value
        /// </summary>
        /// <param name="key"></param>
        /// <param name="configPath"></param>
        /// <returns></returns>
        public string GetAppSettings(string key, string configPath)
        {
            ExeConfigurationFileMap map = new ExeConfigurationFileMap { ExeConfigFilename = configPath };
            var configuration = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
            var strObj = configuration.AppSettings.Settings[key];
            if (strObj == null)
            {
                return null;
            }
            else
            {
                return strObj.Value;
            }
        }
        /// <summary>
        /// 修改指定的XML文件钟add的值
        /// </summary>
        /// <param name="XmlFilePath">文件路径</param>
        /// <param name="Iskey">标签内key的值</param>
        /// <param name="Isvalue">即将被修改的标签内Isvalue的值</param>
        public void ModifyXmlFile(string XmlFilePath, string Iskey, string Isvalue)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(XmlFilePath);
            XmlNodeList nodes = doc.GetElementsByTagName("add");
            XmlAttribute att;
            for (int i = 0; i < nodes.Count; i++)
            {
                //获得将当前元素的key属性  
                att = nodes[i].Attributes["key"];
                //根据元素的第一个属性来判断当前的元素是不是目标元素  
                if (att.Value == Iskey)
                {
                    //对目标元素中的第二个属性赋值  
                    att = nodes[i].Attributes["value"];
                    att.Value = Isvalue;
                    break;
                }
            }
            //保存上面的修改  
            doc.Save(XmlFilePath);
        }
    }
}

 

posted @ 2018-08-27 18:00  wskxy  阅读(834)  评论(0编辑  收藏  举报