zoukankan      html  css  js  c++  java
  • 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 { 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);
            }
        }

    更新文件

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

    事件参数类

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

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

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

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

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

            
    public Manifest Manifest { getset; }
        }

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

            
    public Manifest Manifest { getset; }
        }

        
    public class FileCopyErrorEventArgs : EventArgs
        {
            
    public Exception Error { getset; }

            
    public Manifest Manifest { getset; }
        }

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

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

            
    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打包到主程序中,

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

    作者:风雨彩虹
             
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    修改UISearchBar的Cancel按钮为中文等本地化问题
    Xcode6 运行程序后,右侧Debug区域的Memory显示空白解决方法
    vuec常用插件
    clipboard 实现复制
    vue 表单操作
    vue 常用功能和命令
    关闭警告&关闭eslint
    vue 添加 fastclick的支持
    url编码函数encodeURI和encodeURIComponent
    jsencrypt加解密 &&cryptico
  • 原文地址:https://www.cnblogs.com/zbo/p/2111335.html
Copyright © 2011-2022 走看看