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,  0 512 );
                
while  (nReadSize  >   0 )
                {
                    fs.Write(nbytes, 
0 , nReadSize);
                    nReadSize 
=  ns.Read(nbytes,  0 512 );
                    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, 
0 4 );
                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);
        }

 

 

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

 

源代码下载地址:http://eyesbaby.codeplex.com/

安装版下载地址:http://files.cnblogs.com/yizhuqing/EyesBabySetup10.zip

我的第一款实用工具-眼保程序(EyesBaby)

EyesBaby1.0使用帮助文档

EyesBaby功能实现之窗口拖拽与缩放功能

EyesBaby功能实现之图片控件上添加字符

EyesBaby功能实现之Windows前景色调节器

EyesBaby功能实现之软件更新

EyesBaby功能实现之窗口渐现效果

 

 欢迎加入EyesBaby再次开发小组

 EyesBaby需求反馈小组

 

你可能感兴趣的:(ESB)