zoukankan      html  css  js  c++  java
  • EyesBaby功能实现之软件更新

    因这部分代码比较难看,所以最后贴出来:)。自动更新部分纯属本人根据自己思路开发的。现在c/s自动更新网上有比较成熟的例子,可能我的这种做法不是很好(望大虾手下留情)。贴出来只是为了给大家提供一种参考和选择。

    整个更新程序部分使用到了以下技术:

    1.采用Access记录日志更新

    2.采用XML记录当前版本配置信息

    3.HttpWebRequest下载文件

    4.GZipStream解压缩文件包

    5.System.Diagnostics.Process操作进程

    6.System.IO文件夹/文件复制

    7.ProgressBar和BackgroundWorker显示整个更新版本进度

    奉上CODE:

    1.Access操作类:

    代码
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Data.OleDb;

    namespace LogHelper.BLL
    {
        
    /// <summary>
        
    /// 更新错误日志处理类
        
    /// </summary>
        public class Log
        {
            
    private string _connStr;

            
    public Log(string connStr)
            {
                _connStr 
    = connStr;
            }

            
    /// <summary>
            
    /// 添加一条日志
            
    /// </summary>
            
    /// <param name="title"></param>
            
    /// <param name="content"></param>
            
    /// <returns></returns>
            public bool Add(LogHelper.Model.Log modLog)
            {
                
    bool b = false;
                
    if (!string.IsNullOrEmpty(_connStr))
                {
                    OleDbConnection objConnection 
    = new OleDbConnection(_connStr);
                    
    try
                    {

                        objConnection.Open();
                        
    string insertSql = "insert into LogInfo(Title,Content,CreateDate) values('" + modLog.Title + "','" + modLog.Content + "','" + modLog.CreateDate + "')";
                        OleDbCommand cmd 
    = new OleDbCommand(insertSql,objConnection);
                        cmd.ExecuteNonQuery();
                        b
    = true;
                    }
                    
    catch (Exception ex)
                    { }
                    
    finally
                    {
                        objConnection.Close();
                    }

                }
                
    return b;
            }
        }
    }

    namespace LogHelper.Model
    {
        
    /// <summary>
        
    /// UpdateErrorLog模型
        
    /// </summary>
        public class Log
        {
            
    string _title;

            
    public string Title
            {
                
    get { return _title; }
                
    set { _title = value; }
            }
            
    string _content;

            
    public string Content
            {
                
    get { return _content; }
                
    set { _content = value; }
            }
            
    string _createDate;

            
    public string CreateDate
            {
                
    get { return _createDate; }
                
    set { _createDate = value; }
            }

        }
    }

    2.XML当前版本配置操作类:

    代码
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Windows.Forms;

    namespace EyesBaby
    {
        
    /// <summary>
        
    /// 当前版本配置操作类
        
    /// </summary>
        public class CurrentVesionHelper
        {
            
    private const string _configName = "CurrentInfo.config";

            
    private const string _currentVesionKeyName = "currentVesion";

            
    private const string _updateDateKeyName = "updateDate";

            
    private const string _programNameKeyName = "programName";

            
    private const string _installDirKeyName = "installDir";

            XMLHandle xml 
    = null;

            
    private string _currentVesion;

            
    private string _updateDate;

            
    private string _installDir;

            
    private string _programName;

            
    /// <summary>
            
    /// 安装目录
            
    /// </summary>
            public string InstallDir
            {
                
    get { return _installDir; }
                
    set { _installDir = value; }
            }

            
    /// <summary>
            
    /// 应用程序名称
            
    /// </summary>
            public string ProgramName
            {
                
    get { return _programName; }
                
    set { _programName = value; }
            }

            
    /// <summary>
            
    /// 当前版本
            
    /// </summary>
            public string CurrentVesion
            {
                
    get { return _currentVesion; }
                
    set { _currentVesion = value; }
            }

            
    /// <summary>
            
    /// 更新日期
            
    /// </summary>
            public string UpdateDate
            {
                
    get { return _updateDate; }
                
    set { _updateDate = value; }
            }

            
    public CurrentVesionHelper()
            {
                
    if (!string.IsNullOrEmpty(_configName))
                {
                    
    string filepath = Application.StartupPath +"\\"+ _configName;
                    xml 
    = new XMLHandle();
                    xml.Load(filepath);
                    _currentVesion 
    = xml.GetValueByID(_currentVesionKeyName);
                    _updateDate 
    = xml.GetValueByID(_updateDateKeyName);
                    _installDir 
    = xml.GetValueByID(_installDirKeyName);
                    _programName 
    = xml.GetValueByID(_programNameKeyName);
                }
            }

            
    /// <summary>
            
    /// 更新保存
            
    /// </summary>
            public void UpdateVesion()
            {
                xml.SetValueByID(_currentVesionKeyName, _currentVesion);
                xml.SetValueByID(_updateDateKeyName, _updateDate);
                xml.SetValueByID(_installDirKeyName, _installDir);
                xml.SetValueByID(_programNameKeyName, _programName);
            }
        }
    }

    3.HttpWebRequest下载文件

    代码
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Net;
    using System.IO;

    namespace EyesBaby
    {
        
    /// <summary>
        
    /// 文件下载类
        
    /// </summary>
        public class DownloadClass
        {
            
    public string StrUrl;//文件下载网址
            public string StrFileName;//下载文件保存地址 
            public string strError;//返回结果
            public long lStartPos = 0//返回上次下载字节
            public long lCurrentPos = 0;//返回当前下载字节
            public long lDownloadFile;//返回当前下载文件长度

            
    public void DownloadFile()
            {
                System.IO.FileStream fs;
                
    if (System.IO.File.Exists(StrFileName))
                {
                    fs 
    = System.IO.File.OpenWrite(StrFileName);
                    lStartPos 
    = fs.Length;
                    fs.Seek(lStartPos, System.IO.SeekOrigin.Current);
                    
    //移动文件流中的当前指针 
                }
                
    else
                {
                    fs 
    = new System.IO.FileStream(StrFileName, System.IO.FileMode.Create);
                    lStartPos 
    = 0;
                }

                
    //打开网络连接 
                try
                {
                    System.Net.HttpWebRequest request 
    = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(StrUrl);
                    
    long length = request.GetResponse().ContentLength;
                    lDownloadFile 
    = length;
                    
    if (lStartPos > 0)
                        request.AddRange((
    int)lStartPos); //设置Range值

                    
    //向服务器请求,获得服务器回应数据流 
                    System.IO.Stream ns = request.GetResponse().GetResponseStream();

                    
    byte[] nbytes = new byte[512];
                    
    int nReadSize = 0;
                    nReadSize 
    = ns.Read(nbytes, 0512);
                    
    while (nReadSize > 0)
                    {
                        fs.Write(nbytes, 
    0, nReadSize);
                        nReadSize 
    = ns.Read(nbytes, 0512);
                        lCurrentPos 
    = fs.Length;
                    }

                    fs.Close();
                    ns.Close();
                    strError 
    = "下载完成";

                }
                
    catch (Exception ex)
                {
                    fs.Close();
                    strError 
    = "下载过程中出现错误:" + ex.ToString();
                }

            }
        } 

    }

    4.GZipStream解压缩文件包

    代码
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.IO;
    using System.IO.Compression;
    using System.Windows.Forms;
    using ICSharpCode.SharpZipLib.Zip;

    namespace EyesBaby
    {

        
    public class clsZip
        {
            
    public void CompressFile(string sourceFile, string destinationFile)
            {
                
    // make sure the source file is there
                if (File.Exists(sourceFile) == false)
                    
    throw new FileNotFoundException();

                
    // Create the streams and byte arrays needed
                byte[] buffer = null;
                FileStream sourceStream 
    = null;
                FileStream destinationStream 
    = null;
                GZipStream compressedStream 
    = null;

                
    try
                {
                    
    // Read the bytes from the source file into a byte array
                    sourceStream = new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.Read);

                    
    // Read the source stream values into the buffer
                    buffer = new byte[sourceStream.Length];
                    
    int checkCounter = sourceStream.Read(buffer, 0, buffer.Length);

                    
    if (checkCounter != buffer.Length)
                    {
                        
    throw new ApplicationException();
                    }

                    
    // Open the FileStream to write to
                    destinationStream = new FileStream(destinationFile, FileMode.OpenOrCreate, FileAccess.Write);

                    
    // Create a compression stream pointing to the destiantion stream
                    compressedStream = new GZipStream(destinationStream, CompressionMode.Compress, true);

                    
    // Now write the compressed data to the destination file
                    compressedStream.Write(buffer, 0, buffer.Length);
                }
                
    catch (ApplicationException ex)
                {
                    MessageBox.Show(ex.Message, 
    "压缩文件时发生错误:", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                
    finally
                {
                    
    // Make sure we allways close all streams
                    if (sourceStream != null)
                        sourceStream.Close();

                    
    if (compressedStream != null)
                        compressedStream.Close();

                    
    if (destinationStream != null)
                        destinationStream.Close();
                }
            }

            
    public void DecompressFile(string sourceFile, string destinationFile)
            {
                
    // make sure the source file is there
                if (File.Exists(sourceFile) == false)
                    
    throw new FileNotFoundException();

                
    // Create the streams and byte arrays needed
                FileStream sourceStream = null;
                FileStream destinationStream 
    = null;
                GZipStream decompressedStream 
    = null;
                
    byte[] quartetBuffer = null;

                
    try
                {
                    
    // Read in the compressed source stream
                    sourceStream = new FileStream(sourceFile, FileMode.Open);

                    
    // Create a compression stream pointing to the destiantion stream
                    decompressedStream = new GZipStream(sourceStream, CompressionMode.Decompress, true);

                    
    // Read the footer to determine the length of the destiantion file
                    quartetBuffer = new byte[4];
                    
    int position = (int)sourceStream.Length - 4;
                    sourceStream.Position 
    = position;
                    sourceStream.Read(quartetBuffer, 
    04);
                    sourceStream.Position 
    = 0;
                    
    int checkLength = BitConverter.ToInt32(quartetBuffer, 0);

                    
    byte[] buffer = new byte[checkLength + 100];

                    
    int offset = 0;
                    
    int total = 0;

                    
    // Read the compressed data into the buffer
                    while (true)
                    {
                        
    int bytesRead = decompressedStream.Read(buffer, offset, 100);

                        
    if (bytesRead == 0)
                            
    break;

                        offset 
    += bytesRead;
                        total 
    += bytesRead;
                    }

                    
    // Now write everything to the destination file
                    destinationStream = new FileStream(destinationFile, FileMode.Create);
                    destinationStream.Write(buffer, 
    0, total);

                    
    // and flush everyhting to clean out the buffer
                    destinationStream.Flush();
                }
                
    catch (ApplicationException ex)
                {
                    MessageBox.Show(ex.Message, 
    "解压文件时发生错误:", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                
    finally
                {
                    
    // Make sure we allways close all streams
                    if (sourceStream != null)
                        sourceStream.Close();

                    
    if (decompressedStream != null)
                        decompressedStream.Close();

                    
    if (destinationStream != null)
                        destinationStream.Close();
                }

            }

            
    /// <summary>
            
    /// 功能:解压zip格式的文件。
            
    /// </summary>
            
    /// <param name="zipFilePath">压缩文件路径</param>
            
    /// <param name="unZipDir">解压文件存放路径,为空时默认与压缩文件同一级目录下,跟压缩文件同名的文件夹</param>
            
    /// <param name="err">出错信息</param>
            
    /// <returns>解压是否成功</returns>
            public bool UnZipFile(string zipFilePath, string unZipDir, out string err)
            {
                err 
    = "";
                
    if (zipFilePath == string.Empty)
                {
                    err 
    = "压缩文件不能为空!";
                    
    return false;
                }
                
    if (!File.Exists(zipFilePath))
                {
                    err 
    = "压缩文件不存在!";
                    
    return false;
                }
                
    //解压文件夹为空时默认与压缩文件同一级目录下,跟压缩文件同名的文件夹
                if (unZipDir == string.Empty)
                    unZipDir 
    = zipFilePath.Replace(Path.GetFileName(zipFilePath), Path.GetFileNameWithoutExtension(zipFilePath));
                
    if (!unZipDir.EndsWith("\\"))
                    unZipDir 
    += "\\";
                
    if (!Directory.Exists(unZipDir))
                    Directory.CreateDirectory(unZipDir);

                
    try
                {
                    
    using (ZipInputStream s = new ZipInputStream(File.OpenRead(zipFilePath)))
                    {

                        ZipEntry theEntry;
                        
    while ((theEntry = s.GetNextEntry()) != null)
                        {
                            
    string directoryName = Path.GetDirectoryName(theEntry.Name);
                            
    string fileName = Path.GetFileName(theEntry.Name);
                            
    if (directoryName.Length > 0)
                            {
                                Directory.CreateDirectory(unZipDir 
    + directoryName);
                            }
                            
    if (!directoryName.EndsWith("\\"))
                                directoryName 
    += "\\";
                            
    if (fileName != String.Empty)
                            {
                                
    using (FileStream streamWriter = File.Create(unZipDir + theEntry.Name))
                                {

                                    
    int size = 2048;
                                    
    byte[] data = new byte[2048];
                                    
    while (true)
                                    {
                                        size 
    = s.Read(data, 0, data.Length);
                                        
    if (size > 0)
                                        {
                                            streamWriter.Write(data, 
    0, size);
                                        }
                                        
    else
                                        {
                                            
    break;
                                        }
                                    }
                                }
                            }
                        }
    //while
                    }
                }
                
    catch (Exception ex)
                {
                    err 
    = ex.Message;
                    
    return false;
                }
                
    return true;
            }
    //


        }


    }

    5.System.Diagnostics.Process操作进程

                     // 关闭程序
                        System.Diagnostics.Process[] ps = System.Diagnostics.Process.GetProcessesByName(programName);
                        
    foreach (System.Diagnostics.Process p in ps)
                        {
                            p.Kill();
                        }
               // 重启程序
                        System.Diagnostics.Process.Start(startpath);
      

    6.System.IO文件夹/文件复制

    代码
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.IO;

    namespace EyesBaby
    {
        
    public class CopyFolder
        { 
              
    private   static   int   total   =   0;  
              
    private   int   FileNumber   =   0;     //文件夹文件总数  
       
              
    ///   <summary>  
              
    ///   复制文件夹  
              
    ///   </summary>  
              
    ///   <param   name="sourceDirName">源文件夹</param>  
              
    ///   <param   name="destDirName">目标文件夹</param>  
              //复制文件夹  
            public void CopyDirectory(string sourceDirName, string destDirName)
            {
                
    if (!Directory.Exists(destDirName))
                {
                    Directory.CreateDirectory(destDirName);
                    File.SetAttributes(destDirName, File.GetAttributes(sourceDirName));
                    
    //File.SetAttributes(destDirName,FileAttributes.Normal);  
                }

                
    if (destDirName[destDirName.Length - 1!= Path.DirectorySeparatorChar)
                    destDirName 
    = destDirName + Path.DirectorySeparatorChar;

                
    string[] files = Directory.GetFiles(sourceDirName);
                
    foreach (string file in files)
                {
                    File.Copy(file, destDirName 
    + Path.GetFileName(file), true);
                    File.SetAttributes(destDirName 
    + Path.GetFileName(file), FileAttributes.Normal);
                    total
    ++;
                }
                
    string[] dirs = Directory.GetDirectories(sourceDirName);
                
    foreach (string dir in dirs)
                {
                    CopyDirectory(dir, destDirName 
    + Path.GetFileName(dir));
                }
            }
         
            
    public   static   int   GetFilesCount(System.IO.DirectoryInfo   dirInfo)    
            {
                  
    int   totalFile   =   0;    
                  totalFile   
    +=   dirInfo.GetFiles().Length;    
                  
    foreach   (System.IO.DirectoryInfo   subdir   in   dirInfo.GetDirectories())    
                  {    
                      totalFile   
    +=   GetFilesCount(subdir);    
                  }    
                  
    return   totalFile;    
            }
        }
    }

    7.ProgressBar和BackgroundWorker显示整个更新版本进度

    代码
            // 启动执行
            bkgWorker.RunWorkerAsync();


            
    /// <summary>
            
    /// 设置加载时间值
            
    /// </summary>
            
    /// <param name="text"></param>
            
    /// <param name="value"></param>
            private void SetValue(string text, int value)
            {
                
    // 更新进度
                for (int i = 1; i <= value; i++)
                {
                    bkgWorker.ReportProgress(
    1, text);
                    System.Threading.Thread.Sleep(
    10);
                }
            }

            
    /// <summary>
            
    /// 执行工作
            
    /// </summary>
            
    /// <param name="sender"></param>
            
    /// <param name="e"></param>
            private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
            {
                
    // 调用更新
                CallUpdate();
            }

            
    /// <summary>
            
    /// 操作进程
             
    /// </summary>
            
    /// <param name="sender"></param>
            
    /// <param name="e"></param>
            private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                lblMsg.Text 
    = e.UserState.ToString();
                prgUpdate.Value 
    += e.ProgressPercentage;
            }

            
    /// <summary>
            
    /// 调用更新
             
    /// </summary>
            private void CallUpdate()
            {
                LogHelper.Model.Log modLog 
    = new LogHelper.Model.Log();

                
    // 判断是否有新版本
                 AutoUpdate autoUpdate = new AutoUpdate();
                CurrentVesionHelper currentVesion 
    = new CurrentVesionHelper();

                
    string updatexmlpath = System.Configuration.ConfigurationSettings.AppSettings["updateXmlPath"];
                UpdateXmlHelper updateXml 
    = new UpdateXmlHelper(updatexmlpath);
                
    string oldVesion = currentVesion.CurrentVesion;
                
    string newVesion = updateXml.Vesion;
                
    string newDownURL = updateXml.DownURL;
                
    bool b = autoUpdate.IsNewVesion(newVesion, oldVesion);
                
                
    if (b)
                {
                    
                    
    string filename = newDownURL.Substring(newDownURL.LastIndexOf('/'+ 1);
                    
    string savePath = Application.StartupPath + "/update/" + filename;
                    SetValue(
    "正在下载新版本……"10);
                    
    if (autoUpdate.DownNewEdition(newDownURL, savePath))
                    {
                        
    string installDir = currentVesion.InstallDir = Application.StartupPath;
                        
    string programName = currentVesion.ProgramName;
                       
                        
    string error = string.Empty;
                        
    string zipfilepath = savePath;
                        
    string unzipdir = Application.StartupPath + "\\update\\" + DateTime.Now.ToString("yyyy-MM-dd"+ "\\";
                        SetValue(
    "正在解压文件包……"20);
                        
    // 解压文件包
                          clsZip zip = new clsZip();
                        zip.UnZipFile(zipfilepath, unzipdir, 
    out error);
                        SetValue(
    "正在关闭程序……"10);
                        
    // 关闭程序
                          System.Diagnostics.Process[] ps = System.Diagnostics.Process.GetProcessesByName(programName);
                        
    foreach (System.Diagnostics.Process p in ps)
                        {
                            p.Kill();
                        }
                        SetValue(
    "正在覆盖原安装程序……"20);
                        
    #region 覆盖原安装程序
                           
    // 休息1秒
                           System.Threading.Thread.Sleep(1000);
                        
    string installPath = installDir + "\\" + programName;
                        
    //if (System.IO.Directory.Exists(installPath))
                        
    //{
                        
    //    // 先删除原安装路径
                           
    //    System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(installPath);
                        
    //     dir.Delete(true);
                        
    //    //System.IO.Directory.Delete(installPath, true);
                        
    //}
                        //// 休息3秒
                           //System.Threading.Thread.Sleep(5000);
                        
    // 再将新版本复制到原安装目录
                           CopyFolder copy = new CopyFolder();
                        copy.CopyDirectory(unzipdir, installDir);
                        
    //System.IO.Directory.Move(unzipdir, installDir);

                        
    #endregion
                        
    string exepath = "EyesBaby.exe";
                        
    // 休息3秒
                           System.Threading.Thread.Sleep(3000);
                        
    string startpath = installPath + "\\" + exepath;
                        SetValue(
    "记录新版本……"20);

                        
    // 记录新版本到CurrentInfo.config
                        currentVesion.CurrentVesion = newVesion;
                        currentVesion.UpdateDate 
    = DateTime.Now.ToShortDateString();
                        currentVesion.UpdateVesion();

                        modLog.Content 
    = "更新成功--新版本号:" + newVesion;
                        
    //MessageBox.Show("更新成功!");
                        SetValue("重启程序……"20);
                        
    // 重启程序
                          System.Diagnostics.Process.Start(startpath);

                    }
                    
    else
                    {
                        modLog.Content 
    = "下载最新版本失败";
                        MessageBox.Show(
    "下载最新版本失败!");
                    }
                }
                
    else
                    modLog.Content 
    = "没有发现新版本";
                modLog.Title 
    = "调用更新服务";
                modLog.CreateDate 
    = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");
                bllLog.Add(modLog);
            }

    部分代码也是从网上东拼西凑找出来的,现已丢失源文路径。深感抱歉!

  • 相关阅读:
    c# 生成随机时间
    HttpWebRequest.ReadWriteTimeout 属性
    如果分配给命令的连接位于本地挂起事务中,ExecuteNonQuery 要求命令拥有事务。命令的 Transaction 属性尚未初始化
    Host 'XXX' is not allowed to connect to this MySQL server 解决方案/如何开启MySQL的远程帐号
    C# winform 获取当前路径
    c# 操作符重载
    为何好男人总被坏女人搞定?【转】
    MySQL,SQLSERVER,ORACLE获取数据库表名及字段名
    病毒加壳技术与脱壳杀毒方法解析
    配置linux DNS
  • 原文地址:https://www.cnblogs.com/jcomet/p/1700407.html
Copyright © 2011-2022 走看看