zoukankan      html  css  js  c++  java
  • 版本更新基本操作

    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(@"SOFTWAREMicrosoftWindowsCurrentVersionApp PathsWinRAR.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);
            }
        }
    }
  • 相关阅读:
    codeforces 701 D. As Fast As Possible(数学题)
    codeforces 807 E. Prairie Partition(贪心+思维)
    codeforces 807 D. Dynamic Problem Scoring(贪心+思维)
    codeforces 807 C. Success Rate(二分)
    Atcoder C
    Atcoder D
    hdu 3308 LCIS(线段树区间合并)
    SpringMVC学习笔记---
    Composer Yii2 不设置全局变量 归档安装 Win7
    电脑硬件扫盲--CPU 显卡
  • 原文地址:https://www.cnblogs.com/wskxy/p/9543768.html
Copyright © 2011-2022 走看看