winform c# 自动更新

来源:互联网 发布:梅西2016年个人数据 编辑:程序博客网 时间:2024/05/17 19:19

 

winform  c# 自动更新,首先预览下截图

 

自动更新一般分3部分:

1、发现更新

2、下载文件

3、复制文件

 http://www.cnblogs.com/liubiaocai/archive/2011/07/18/2109183.html

下面对以上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 { getset; }

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

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

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

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

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

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

    
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 { getset; }

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

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

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

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

    
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 { getset; }

        
public Manifest Manifest { getset; }
    }

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

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

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

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

        
public Manifest Manifest { getset; }
    }

 下载代码

 

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, 
nullnull);
        }

        
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);
        }
    }

 

源代码下载:  http://files.cnblogs.com/liubiaocai/Updater.rar

原创粉丝点击