winform更新程序代码

这是我的第一个随笔,写的不好的或者语法错误等,请大家不要见怪,首先预览下截图

winform更新程序代码 

自动更新一般分3部分:

1、发现更新

2、下载文件

3、复制文件

 

下面对以上3个过程做简单的介绍

发现更新

根据客户端的配置文件的manifestUri去读取服务器的xml文件,然后依次比较applicationId和version,如果applicationId一致且version不一致则可以更新,客户端配置文件不是app.config,而是一个自己定义的xml文件,至于为什么不用app.config文件的原因很简单,因为app.config在系统运行的时候是不能进行修改的,客户端配置文件内容大概如下:

<? xml version="1.0" encoding="utf-8" ?>
< applicationUpdater  applicationId ="{4a1e1623-bd3c-4921-8d91-85d34a5fe518}"
                        manifestUri
="http://127.0.0.1/manifests.xml"
                        version
="1.04" >
</ applicationUpdater >

 

applicationId表示运用程序Id,这个要跟服务器上的xml的applicationId一致,否则程序不会更新;
manifestUri表示服务器xml的地址
version表示当前版本,版本跟服务器上的不一致就更新
 
服务器端配置文件内容大概如下:
<? xml version="1.0" encoding="utf-8"  ?>
< manifest >
  
<!-- 版本号,无格式要求,更新时需要修改 -->
  
< version > 1.2 </ version >
  
< description > 更新说明,更新时需要修改 </ description >
  
<!-- applicationId运用程序ID,无格式要求,需要与客户端配置一样,否则不会进行更新 -->
  
< application  applicationId ="{215E1AD7-9ABA-432f-A952-24BABA556850}" >
    
<!-- 重新启动exe名称,parameters启动时传入的参数 -->
    
< entryPoint  file ="Client.exe"  parameters ="client"   />
    
<!-- 更新文件的目录,相对于更新系统,默认为同级目录 -->
    
< location > . </ location >
  
</ application >
  
<!-- base表示存放该文件的url -->
  
< files  base ="http://localhost/update/" >
    
<!-- 文件名称,更新时需要修改 -->
    
< file  source ="test.txt"   />
    
< file  source ="Client.exe"   />
  
</ files >
</ manifest >
XML对应的实体类
View Code
[XmlRoot( " manifest " )]
    
public   class  Manifest
    {
        [XmlElement(
" version " )]
        
public   string  Version {  get set ; }

        [XmlElement(
" description " )]
        
public   string  Description {  get set ; }

        [XmlElement(
" fileBytes " )]
        
public   long  FileBytes {  get set ; }

        [XmlElement(
" application " )]
        
public  Application Application {  get set ; }

        [XmlElement(
" files " )]
        
public  ManifestFiles ManifestFiles {  get set ; }
    }

    
public   class  ManifestFiles
    {
        [XmlElement(
" file " )]
        
public  ManifestFile[] Files {  get set ; }

        [XmlAttribute(
" base " )]
        
public   string  BaseUrl {  get set ; }
    }

    
public   class  ManifestFile
    {
        [XmlAttribute(
" source " )]
        
public   string  Source
        {
            
get ;
            
set ;
        }

        [XmlAttribute(
" hash " )]
        
public   string  Hash
        {
            
get ;
            
set ;
        }
    }

    
public   class  Application
    {
        [XmlAttribute(
" applicationId " )]
        
public   string  ApplicationId {  get set ; }

        [XmlElement(
" location " )]
        
public   string  Location {  get set ; }

        [XmlElement(
" entryPoint " )]
        
public  EntryPoint EntryPoint {  get set ; }
    }

    
public   class  EntryPoint
    {
        [XmlAttribute(
" file " )]
        
public   string  File {  get set ; }

        [XmlAttribute(
" parameters " )]
        
public   string  Parameters {  get set ; }
    }

    
public   class  UpdaterConfigurationView
    {
        
private   static  XmlDocument document  =   new  XmlDocument();
        
private   static   readonly   string  xmlFileName  =  Path.Combine(AppDomain.CurrentDomain.BaseDirectory,  " updateconfiguration.config " );

        
static  UpdaterConfigurationView()
        {
            document.Load(xmlFileName);
        }

        
public   string  Version
        {
            
get
            {
                
return  document.SelectSingleNode( " applicationUpdater " ).Attributes[ " version " ].Value;
            }
            
set
            {
                document.SelectSingleNode(
" applicationUpdater " ).Attributes[ " version " ].Value  =  value;
                document.Save(xmlFileName);
            }
        }

        
public   string  ApplicationId
        {
            
get
            {
                
return  document.SelectSingleNode( " applicationUpdater " ).Attributes[ " applicationId " ].Value;
            }
            
set
            {
                document.SelectSingleNode(
" applicationUpdater " ).Attributes[ " applicationId " ].Value  =  value;
                document.Save(xmlFileName);
            }
        }

        
public   string  ManifestUri
        {
            
get
            {
                
return  document.SelectSingleNode( " applicationUpdater " ).Attributes[ " manifestUri " ].Value;
            }
            
set
            {
                document.SelectSingleNode(
" applicationUpdater " ).Attributes[ " manifestUri " ].Value  =  value;
                document.Save(xmlFileName);
            }
        }
    }
 
 
 
下载文件
 下载文件是根据服务器端的配置文件进行的,配置文件设置了下载的文件路径,下载地址的url,下载文件保存的位置,由location节点设置,好了,不多说了,看下载的源码,这里我是写了一个可以异步下载的组件,里面用的是Ms自带的WebClient类,异步下载有事件通知,详见源码:
事件类
View Code
public   class  DownloadErrorEventArgs : EventArgs
    {
        
public  Exception Error {  get set ; }

        
public  Manifest Manifest {  get set ; }
    }

    
public   class  DownloadProgressEventArgs : ProgressChangedEventArgs
    {
        
public  DownloadProgressEventArgs( int  progressPercentage,  object  userState)
            : 
base (progressPercentage,userState)
        { }

        
///   <summary>
        
///  当前下载的文件名
        
///   </summary>
         public   string  FileName {  get set ; }

        
///   <summary>
        
///  获取收到的字节数。
        
///   </summary>
         public   long  BytesReceived {  get set ; }
        
///   <summary>
        
///  获取 System.Net.WebClient 数据下载操作中的字节总数。
        
///   </summary>
         public   long  TotalBytesToReceive {  get set ; }
    }

    
public   class  DownloadCompleteEventArgs : AsyncCompletedEventArgs
    {
        
public  DownloadCompleteEventArgs(Exception error,  bool  cancelled,  object  userState)
            : 
base (error, cancelled, userState)
        { 
        }

        
public  Manifest Manifest {  get set ; }
    }

 下载代码

 

View Code
public   class  DownloadClass : Component
    {
        
private  WebClient webClient = new  WebClient();
        
private  Manifest manifest;
        
private   int  fileCount  =   0 ;
        
private   bool  cancel  =   false ;
        
private   string  tempPath  =  Path.Combine(AppDomain.CurrentDomain.BaseDirectory,  " temp " );

        
private  HybridDictionary userStateToLifetime  =   new  HybridDictionary();
        
private   object  defaultTaskId  =   new   object ();
        
private   delegate   void  WorkerEventHandler(AsyncOperation asyncOp);
        
private  System.ComponentModel.Container components  =   null ;
        
private  SendOrPostCallback onProgressReportDelegate;
        
private  SendOrPostCallback onCompletedDelegate;
        
private  AsyncOperation current;

        
///   <summary>
        
///  下载进度
        
///   </summary>
         public   event  EventHandler < DownloadProgressEventArgs >  DownloadProgressChanged;
        
///   <summary>
        
///  下载完成事件
        
///   </summary>
         public   event  EventHandler < DownloadCompleteEventArgs >  DownloadCompleted;
        
///   <summary>
        
///  下载错误触发的事件
        
///   </summary>
         public   event  EventHandler < DownloadErrorEventArgs >  DownloadError;

        
public  DownloadClass(IContainer container)
        {
            container.Add(
this );
            InitializeComponent();
            InitializeDelegates();
        }

        
public  DownloadClass()
        {
            InitializeComponent();
            InitializeDelegates();
        }

        
///   <summary>
        
///  初始化代理
        
///   </summary>
         protected   virtual   void  InitializeDelegates()
        {
            onProgressReportDelegate 
=   new  SendOrPostCallback(ReportProgress);
            onCompletedDelegate 
=   new  SendOrPostCallback(DoDownloadCompleted);
        }

        
///   <summary>
        
///  触发下载进度事件
        
///   </summary>
        
///   <param name="e"></param>
         protected   virtual   void  OnDownloadProgressChanged(DownloadProgressEventArgs e)
        {
            
if  (DownloadProgressChanged  !=   null )
            {
                DownloadProgressChanged(
this , e);
            }
        }

        
///   <summary>
        
///  触发下载完成事件
        
///   </summary>
        
///   <param name="e"></param>
         protected   virtual   void  OnDownloadCompleted(DownloadCompleteEventArgs e)
        {
            
if  (DownloadCompleted  !=   null )
            {
                DownloadCompleted(
this , e);
            }
        }

        
///   <summary>
        
///  触发下载错误事件
        
///   </summary>
        
///   <param name="e"></param>
         protected   virtual   void  OnDownloadError(DownloadErrorEventArgs e)
        {
            
if  (DownloadError  !=   null )
            {
                DownloadError(
this , e);
            }
        }

        
///   <summary>
        
///  下载文字保存的临时目录
        
///   </summary>
         public   string  TempPath
        {
            
get
            {
                
return  tempPath;
            }
            
set
            {
                tempPath 
=  value;
            }
        }

        
///   <summary>
        
///  同步下载
        
///   </summary>
        
///   <param name="manifest"></param>
         public   void  Download(Manifest manifest)
        {
            Init(manifest);
            
foreach  (var file  in  manifest.ManifestFiles.Files)
            {
                
string  serverFileName  =  Path.Combine(manifest.ManifestFiles.BaseUrl, file.Source);
                
string  clientFileName  =  Path.Combine(tempPath, file.Source);
                Uri uri 
=   new  Uri(serverFileName);
                
if  ( ! Directory.Exists(Path.GetDirectoryName(clientFileName)))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(clientFileName));
                }
                webClient.DownloadFile(uri, clientFileName);
            }
        }

        
///   <summary>
        
///  异步下载
        
///   </summary>
        
///   <param name="manifest"></param>
         public   void  DownloadAsync(Manifest manifest)
        {
            Init(manifest);
            DownloadAsync(manifest,defaultTaskId);
        }

        
///   <summary>
        
///  异步下载并指定任务Id
        
///   </summary>
        
///   <param name="manifest"></param>
        
///   <param name="taskId"></param>
         public   void  DownloadAsync(Manifest manifest, object  taskId)
        {
            AsyncOperation asyncOp 
=  AsyncOperationManager.CreateOperation(taskId);
            
lock  (userStateToLifetime.SyncRoot)
            {
                
if  (userStateToLifetime.Contains(taskId))
                {
                    
throw   new  ArgumentException( " 参数taskId必须是唯一的 " " taskId " );
                }
                userStateToLifetime[taskId] 
=  asyncOp;
            }
            WorkerEventHandler workerDelegate 
=   new  WorkerEventHandler(DownloadWorker);
            workerDelegate.BeginInvoke(asyncOp, 
null null );
        }

        
private   void  Init(Manifest manifest)
        {
            
this .manifest  =  manifest;
            webClient.BaseAddress 
=  manifest.ManifestFiles.BaseUrl;
            webClient.Credentials 
=  CredentialCache.DefaultCredentials;
            webClient.Encoding 
=  Encoding.UTF8;
        }

        
///   <summary>
        
///  异步下载方法
        
///   </summary>
        
///   <param name="asyncOp"></param>
         private   void  DownloadWorker(AsyncOperation asyncOp)
        {
            current 
=  asyncOp;
            
if  ( ! TaskCanceled(asyncOp.UserSuppliedState))
            {
                
try
                {
                    webClient.DownloadFileCompleted 
+=   new  AsyncCompletedEventHandler(webClient_DownloadFileCompleted);
                    webClient.DownloadProgressChanged 
+=   new  DownloadProgressChangedEventHandler(webClient_DownloadProgressChanged);
                    
foreach  (var file  in  manifest.ManifestFiles.Files)
                    {
                        
string  serverFileName  =  Path.Combine(manifest.ManifestFiles.BaseUrl, file.Source);
                        
string  clientFileName  =  Path.Combine(tempPath, file.Source);
                        Uri uri 
=   new  Uri(serverFileName);
                        
if  ( ! Directory.Exists(Path.GetDirectoryName(clientFileName)))
                        {
                            Directory.CreateDirectory(Path.GetDirectoryName(clientFileName));
                        }
                        
while  (webClient.IsBusy)
                        {
                            
// 阻塞异步下载
                        }
                        
if  ( ! cancel)
                        {
                            webClient.DownloadFileAsync(uri, clientFileName, file.Source);
                        }
                    }
                }
                
catch  (Exception ex)
                {
                    DownloadErrorEventArgs e 
=   new  DownloadErrorEventArgs();
                    e.Error 
=  ex;
                    e.Manifest 
=  manifest;
                    OnDownloadError(e);
                }
            }
        }

        
///   <summary>
        
///  异步完成方法
        
///   </summary>
        
///   <param name="exception"></param>
        
///   <param name="canceled"></param>
        
///   <param name="asyncOp"></param>
         private   void  CompletionMethod(Exception exception,  bool  canceled, AsyncOperation asyncOp)
        {
            
if  ( ! canceled)
            {
                
lock  (userStateToLifetime.SyncRoot)
                {
                    userStateToLifetime.Remove(asyncOp.UserSuppliedState);
                }
            }
            DownloadCompleteEventArgs e 
=   new  DownloadCompleteEventArgs(exception, canceled, asyncOp.UserSuppliedState);
            e.Manifest 
=  manifest;
            asyncOp.PostOperationCompleted(onCompletedDelegate, e);
            current 
=   null ;
        }

        
///   <summary>
        
///  异步下载进度事件(仅对于单个文件)
        
///   </summary>
        
///   <param name="sender"></param>
        
///   <param name="e"></param>
         void  webClient_DownloadProgressChanged( object  sender, DownloadProgressChangedEventArgs e)
        {
            DownloadProgressEventArgs args 
=   new  DownloadProgressEventArgs(e.ProgressPercentage, e.UserState);
            args.BytesReceived 
=  e.BytesReceived;
            args.FileName 
=  e.UserState.ToString();
            args.TotalBytesToReceive 
=  e.TotalBytesToReceive;
            
if  (current  !=   null )
            {
                current.Post(onProgressReportDelegate, args);
            }
        }

        
///   <summary>
        
///  异步下载完成事件(仅对于单个文件)
        
///   </summary>
        
///   <param name="sender"></param>
        
///   <param name="e"></param>
         void  webClient_DownloadFileCompleted( object  sender, AsyncCompletedEventArgs e)
        {
            fileCount
++ ;
            
if  (fileCount  ==  manifest.ManifestFiles.Files.Length)
            {
                
this .CompletionMethod(e.Error, TaskCanceled(current.UserSuppliedState), current);
            }
        }

        
///   <summary>
        
///  取消异步下载
        
///   </summary>
         public   void  CancelAsync()
        {
            CancelAsync(defaultTaskId);
        }

        
///   <summary>
        
///  取消异步下载
        
///   </summary>
         public   void  CancelAsync( object  taskId)
        {
            webClient.CancelAsync();
            cancel 
=   true ;
            current 
=   null ;
            AsyncOperation asyncOp 
=  userStateToLifetime[taskId]  as  AsyncOperation;
            
if  (asyncOp  !=   null )
            {
                
lock  (userStateToLifetime.SyncRoot)
                {
                    userStateToLifetime.Remove(taskId);
                }
            }
        }

        
private   bool  TaskCanceled( object  taskId)
        {
            
return  cancel  ||  (userStateToLifetime[taskId]  ==   null );
        }
        
        
private   void  InitializeComponent()
        {
            components 
=   new  System.ComponentModel.Container();
        }

        
protected   override   void  Dispose( bool  disposing)
        {
            
if  (disposing)
            {
                
if  (components  !=   null )
                {
                    components.Dispose();
                }
            }
            
base .Dispose(disposing);
        }

        
private   void  DoDownloadCompleted( object  operationState)
        {
            DownloadCompleteEventArgs e 
=  operationState  as  DownloadCompleteEventArgs;
            OnDownloadCompleted(e);
        }

        
private   void  ReportProgress( object  state)
        {
            DownloadProgressEventArgs e 
=  state  as  DownloadProgressEventArgs;
            OnDownloadProgressChanged(e);
        }
    }

 

更新文件

也就是把下载的文件覆盖到客户端安装的目录,代码如下:

事件参数类

 

View Code
  ///   <summary>
    
///  文件复制进度报告事件参数
    
///   </summary>
     public   class  FileCopyProgressChangedEventArgs : ProgressChangedEventArgs
    {
        
public  FileCopyProgressChangedEventArgs( int  progressPercentage,  object  userState)
            : 
base (progressPercentage, userState)
        {
        }

        
///   <summary>
        
///  当前复制的字节数
        
///   </summary>
         public   double  BytesToCopy {  get set ; }

        
///   <summary>
        
///  当前复制操作中的字节总数
        
///   </summary>
         public   double  TotalBytesToCopy {  get set ; }

        
///   <summary>
        
///  当前复制的源文件名
        
///   </summary>
         public   string  SourceFileName {  get set ; }

        
///   <summary>
        
///  当前复制的目标文件名
        
///   </summary>
         public   string  TargetFileName {  get set ; }

        
public  Manifest Manifest {  get set ; }
    }

    
///   <summary>
    
///  文件复制完成事件参数
    
///   </summary>
     public   class  FileCopyCompletedEventArgs : AsyncCompletedEventArgs
    {
        
public  FileCopyCompletedEventArgs(Exception error,  bool  cancelled,  object  userState)
            : 
base (error, cancelled, userState)
        {
        }

        
public  Manifest Manifest {  get set ; }
    }

    
public   class  FileCopyErrorEventArgs : EventArgs
    {
        
public  Exception Error {  get set ; }

        
public  Manifest Manifest {  get set ; }
    }

 

文件复制类,可以使用异步复制,异步复制提供了事件通知的机制,即可以有进度报告,文件复制也是一个组件类

 

View Code
  ///   <summary>
    
///  文件复制组件类
    
///   </summary>
     public   class  FileCopyClass : Component
    {
        
private   object  defaultTaskId  =   new   object ();
        
private   int  writeFileLength  =   1024   *   64 ;

        
private   delegate   void  WorkerEventHandler(Manifest manifest,  string  sourcePath, AsyncOperation asyncOp);

        
private  SendOrPostCallback onProgressReportDelegate;
        
private  SendOrPostCallback onCompletedDelegate;

        
private  HybridDictionary userStateToLifetime  =   new  HybridDictionary();

        
private  System.ComponentModel.Container components  =   null ;

        
#region  Public events

        
///   <summary>
        
///  文件复制进度事件
        
///   </summary>
         public   event  EventHandler < FileCopyProgressChangedEventArgs >  FileCopyProgressChanged;
        
///   <summary>
        
///  文件复制完成事件
        
///   </summary>
         public   event  EventHandler < FileCopyCompletedEventArgs >  FileCopyCompleted;

        
public   event  EventHandler < FileCopyErrorEventArgs >  FileCopyError;

        
#endregion

        
#region  Construction and destruction

        
public  FileCopyClass(IContainer container)
        {
            container.Add(
this );
            InitializeComponent();
            InitializeDelegates();
        }

        
public  FileCopyClass()
        {
            InitializeComponent();
            InitializeDelegates();
        }

        
protected   virtual   void  InitializeDelegates()
        {
            onProgressReportDelegate 
=   new  SendOrPostCallback(ReportProgress);
            onCompletedDelegate 
=   new  SendOrPostCallback(CopyCompleted);
        }

        
protected   override   void  Dispose( bool  disposing)
        {
            
if  (disposing)
            {
                
if  (components  !=   null )
                {
                    components.Dispose();
                }
            }
            
base .Dispose(disposing);
        }

        
#endregion

        
#region  实现

        
public   int  WriteFileLength
        {
            
set
            {
                writeFileLength 
=  value;
            }
        }

        
public   void  Copy(Manifest manifest,  string  sourcePath)
        {
            
string [] sourceFiles  =   null ;
            
string [] targetFiles  =   null ;
            GetFiles(manifest, sourcePath, 
out  sourceFiles,  out  targetFiles);
            
for  ( int  i  =   0 ; i  <  sourceFiles.Length; i ++ )
            {
                
if  ( ! Directory.Exists(Path.GetDirectoryName(targetFiles[i])))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(targetFiles[i]));
                }
                File.Copy(sourceFiles[i], targetFiles[i], 
true );
            }
        }

        
public   void  CopyAsync(Manifest manifest,  string  sourcePath)
        {
            CopyAsync(manifest, sourcePath, defaultTaskId);
        }

        
public   void  CopyAsync(Manifest manifest,  string  sourcePath,  object  taskId)
        {
            AsyncOperation asyncOp 
=  AsyncOperationManager.CreateOperation(taskId);
            
lock  (userStateToLifetime.SyncRoot)
            {
                
if  (userStateToLifetime.Contains(taskId))
                {
                    
throw   new  ArgumentException( " 参数taskId必须是唯一的 " " taskId " );
                }
                userStateToLifetime[taskId] 
=  asyncOp;
            }

            WorkerEventHandler workerDelegate 
=   new  WorkerEventHandler(FileCopyWorker);
            workerDelegate.BeginInvoke(manifest, sourcePath, asyncOp, 
null null );
        }

        
private   bool  TaskCanceled( object  taskId)
        {
            
return  (userStateToLifetime[taskId]  ==   null );
        }

        
public   void  CancelAsync()
        {
            CancelAsync(defaultTaskId);
        }

        
public   void  CancelAsync( object  taskId)
        {
            AsyncOperation asyncOp 
=  userStateToLifetime[taskId]  as  AsyncOperation;
            
if  (asyncOp  !=   null )
            {
                
lock  (userStateToLifetime.SyncRoot)
                {
                    userStateToLifetime.Remove(taskId);
                }
            }
        }

        
private   void  FileCopyWorker(Manifest manifest,  string  sourcePath, AsyncOperation asyncOp)
        {
            Exception exception 
=   null ;
            FileCopyProgressChangedEventArgs e 
=   null ;
            Stream rStream 
=   null ;
            Stream wStream 
=   null ;
            
double  writeBytes  =   0 ;
            
string [] sourceFiles  =   null
            
string [] targetFiles  =   null ;
            GetFiles(manifest, sourcePath,
out  sourceFiles, out  targetFiles);
            
if  ( ! TaskCanceled(asyncOp.UserSuppliedState))
            {
                
try
                {
                    
double  totalBytes  =  GetFileLength(sourceFiles);
                    
byte [] buffer  =   new   byte [writeFileLength];
                    
int  len  =   0 ;
                    
int  offset  =   0 ;
                    
for  ( int  i  =   0 ; i  <  sourceFiles.Length; i ++ )
                    {
                        
try
                        {
                            
if  ( ! Directory.Exists(Path.GetDirectoryName(targetFiles[i])))
                            {
                                Directory.CreateDirectory(Path.GetDirectoryName(targetFiles[i]));
                            } 
                            rStream 
=   new  FileStream(sourceFiles[i], FileMode.Open, FileAccess.Read, FileShare.None);
                            wStream 
=   new  FileStream(targetFiles[i], FileMode.Create, FileAccess.Write, FileShare.None);
                            
while  ((len  =  rStream.Read(buffer, offset, writeFileLength))  >   0 )
                            {
                                wStream.Write(buffer, offset, len);
                                writeBytes 
+=  len;
                                e 
=   new  FileCopyProgressChangedEventArgs(( int )(writeBytes  /  totalBytes  *   100 ), asyncOp.UserSuppliedState);
                                e.SourceFileName 
=  sourceFiles[i];
                                e.TargetFileName 
=  targetFiles[i];
                                e.TotalBytesToCopy 
=  totalBytes;
                                e.BytesToCopy 
=  len;
                                e.Manifest 
=  manifest;
                                asyncOp.Post(
this .onProgressReportDelegate, e);
                                Thread.Sleep(
1 );
                            }
                        }
                        
finally
                        {
                            DisposeStream(wStream);
                            DisposeStream(rStream);
                        }
                    }
                }
                
catch  (Exception ex)
                {
                    exception 
=  ex;
                    OnFileCopyError(
new  FileCopyErrorEventArgs() { Error  =  ex, Manifest  =  manifest });
                }
            }
            
this .CompletionMethod(manifest, exception, TaskCanceled(asyncOp.UserSuppliedState), asyncOp);
        }

        
private   void  GetFiles(Manifest manifest,  string  sourcePath, out   string [] sourceFiles, out   string [] targetFiles)
        {
            sourceFiles 
=   new   string [manifest.ManifestFiles.Files.Length];
            targetFiles 
=   new   string [manifest.ManifestFiles.Files.Length];
            
string  path  =  Path.GetFullPath(manifest.Application.Location);
            
for  ( int  i  =   0 ; i  <  manifest.ManifestFiles.Files.Length; i ++ )
            {
                sourceFiles[i] 
=  Path.Combine(sourcePath, manifest.ManifestFiles.Files[i].Source);
                targetFiles[i] 
=  Path.Combine(path, manifest.ManifestFiles.Files[i].Source);
            }
        }

        
private   void  DisposeStream(Stream stream)
        {
            
if  (stream  !=   null )
            {
                stream.Flush();
                stream.Close();
                stream.Dispose();
            }
        }

        
private   double  GetFileLength( string [] sourceFiles)
        {
            
double  bytes  =   0 ;
            
foreach  (var file  in  sourceFiles)
            {
                FileInfo fileInfo 
=   new  FileInfo(file);
                bytes 
+=  fileInfo.Length;
            }
            
return  bytes;
        }

        
private   void  CopyCompleted( object  operationState)
        {
            FileCopyCompletedEventArgs e 
=  operationState  as  FileCopyCompletedEventArgs;

            OnFileCopyCompleted(e);
        }

        
private   void  ReportProgress( object  state)
        {
            FileCopyProgressChangedEventArgs e 
=  state  as  FileCopyProgressChangedEventArgs;

            OnProgressChanged(e);
        }

        
protected   void  OnFileCopyCompleted(FileCopyCompletedEventArgs e)
        {
            
if  (FileCopyCompleted  !=   null )
            {
                FileCopyCompleted(
this , e);
            }
        }

        
protected   void  OnProgressChanged(FileCopyProgressChangedEventArgs e)
        {
            
if  (FileCopyProgressChanged  !=   null )
            {
                FileCopyProgressChanged(
this , e);
            }
        }

        
protected   void  OnFileCopyError(FileCopyErrorEventArgs e)
        {
            
if  (FileCopyError  !=   null )
            {
                FileCopyError(
this , e);
            }
        }

        
private   void  CompletionMethod(Manifest manifest, Exception exception,  bool  canceled, AsyncOperation asyncOp)
        {
            
if  ( ! canceled)
            {
                
lock  (userStateToLifetime.SyncRoot)
                {
                    userStateToLifetime.Remove(asyncOp.UserSuppliedState);
                }
            }

            FileCopyCompletedEventArgs e 
=   new  FileCopyCompletedEventArgs(exception, canceled, asyncOp.UserSuppliedState);
            e.Manifest 
=  manifest;
            asyncOp.PostOperationCompleted(onCompletedDelegate, e);
        }

        
#endregion

        
private   void  InitializeComponent()
        {
            components 
=   new  System.ComponentModel.Container();
        }
    }

 

 好了,基本的代码已经完成了,其他都是客户端调用的代码,客户端有2个exe程序,一个是主程序,另外一个是更新程序,所以使用2个exe的原因是,主程序在打开的情况是无法进行更新的,就是文件不能被覆盖,那么主程序只要引用上面写的程序的dll,以及一个配置文件,配置文件的名称在程序写死了的,默认是在exe目录,名称为updateconfiguration.config,主程序只要调用UpdateClass类的CheckForUpdates方法就可以了

Demo

下面说下整体的部署方式

服务器:一个配置文件,记录更新的文件,记录的文件目录一定是存在的,否则会出现404错误

客户端:主程序+更新程序+配置文件,即把更新程序编译后的exe打包到主程序中,

 

以上程序进行了简单的测试,如果您下载使用了出现了问题,请及时联系我。

 

 

 

作者: 风雨彩虹
         
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

你可能感兴趣的:(WinForm)