winform+wcf搭建商户管理系统(4)- 在线自动更新功能的实现

  • 功能展示

实现winform的在线更新,我这里主要实现了3部分的功能:

1.登录后检查更新

 

2.实现软件在运行中的实时更新提醒

3.在确认更新之后的在线更新功能

  • 代码说明

1.实现登录时的检查更新

               //检查版本更新
                string version = Application.ProductVersion.ToString();
                bool update = _client.TLoginCheckUpdate(version);
                if (update)
                {
                    DialogResult dialogResult = MessageBox.Show("系统存在更新,是否现在升级?", "升级提示", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
                    if (dialogResult == DialogResult.Yes)
                    {
                        System.Diagnostics.Process.Start(Path.Combine(Application.StartupPath, "Update.exe"), "true");
                        Application.Exit();
                        return;
                    }
                }

  

 在登录完成之后,获取本地主程序的的版本级别,远程与服务器最新版本的客户端版本号进行比较,从而获取版本是否需要更新。

在选择更新的时候,关闭主程序进程,运行更新程序。

2.主程序的实时更新检查

检查版本线程

private void FormMain_Load(object sender, EventArgs e)
        {
            try
            {               
                label1.Visible = true;
                backgroundWorker1.RunWorkerAsync();
                tmTime.Start();
             
                //开一个检测系统更新的线程
                Thread thread = new Thread(new ParameterizedThreadStart(delegate
                {
                    while (true)
                    {
                        //在线检查更新
                        bool result = _client.TLoginCheckUpdate(Application.ProductVersion.ToString());
                        if (result && OnCanBlinkChanged != null && _worned == false)
                        {
                            Action actionDelegate = () =>
                            {
                               OnCanBlinkChanged(this, new OparateEventArgs(true));
                            };
                            this.Invoke(actionDelegate);
                            _worned = true;
                        }
                        Thread.Sleep(10000);
                    }
                }));
                thread.IsBackground = true;
                thread.Start();
            }
            catch (Exception ex)
            {
                warningBox1.ShowMessage(ex.Message, MessageType.Error, 3000, Color.Red);
            }
        }

  获取到版本更新之后,提醒用户,然后闪烁Notify图标

  private static void main_OnCanBlinkChanged(object sender, OparateEventArgs e)
        {
            if (e.CanOparate)
            {
                _recivedMessage = true;
                _notify.ShowBalloonTip(3000, "更新提醒", "系统出现了新版本", ToolTipIcon.Info);
                _timer.Start();
            }
        }

        private static void timer_Tick(object sender, EventArgs e)
        {
            if (!_blink)
            {
                _notify.Icon = Resources.main;
            }
            else
            {
                _notify.Icon = Resources.blank;
            }
            _blink = !_blink;  
        }

  3.在线更新的实现

远程获取需要新增、删除或者更新的文件列表

客户端代码

        private void InitializeLstView()
        {
            string[] tempLst = null;
            //获取当前的系统版本号
            string rootUrl = Application.StartupPath;
            List<string> conditions = new List<string>();
            string[] files = Directory.GetFiles(rootUrl);
            foreach (var item in files)
            {
                if (item.EndsWith("dll") || item.EndsWith("exe"))
                {
                    FileVersionInfo version = FileVersionInfo.GetVersionInfo(item);
                    conditions.Add(Path.GetFileName(item) + ',' + version.FileVersion);
                }
                else
                {
                    conditions.Add(Path.GetFileName(item) + ',');   //listView1.Items.Add(new ListViewItem(new string[] { Path.GetFileName(item), "", "" }));
                }
            }
            bool result = _client.TLoginUpdateSys(out tempLst, out _deleteLst, out _fileContent, conditions.ToArray());
            if (result)
            {
                //添加删除列表
                if (_deleteLst != null && _deleteLst.Length > 0)
                {
                    lvUpdateList.Items.Add(new ListViewItem(new string[] { "文件删除个数:" + _deleteLst.Length, "", "0%" }));
                }

                //添加更新列表
                List<string> lstFile = new List<string>();
                foreach (string item in tempLst)
                {
                    string[] arr = item.Split(';');
                    if (arr != null && arr.Length > 1)
                    {
                        string[] fileTemp = arr[0].Split('\\');
                        lvUpdateList.Items.Add(new ListViewItem(new string[] { fileTemp[fileTemp.Length - 1], arr[1], "0%" }));
                        lstFile.Add(arr[0]);
                    }
                }              
                _fileLst = lstFile.ToArray();
            }
            else
            {
                lbState.Text = "获取更新文件失败!";
            }
            btnFinish.Enabled = !result;
            btnNext.Enabled = result;
        }

  服务端代码

        public bool Update(string[] currentFileVesion,out string[] uploadFileLst,out string[] deleteFileLst,out byte[][] fileContent)
        {
            bool result = true;
            try
            {
                uploadFileLst = null;
                fileContent = null;
                deleteFileLst = null;
                //记录原始版本,用于获取删除文件
                Dictionary<string,string> sourceVesion = new Dictionary<string,string>();
                if (currentFileVesion == null)
                    return false;
                Array.ForEach(currentFileVesion, t =>
                    {
                        //fileName,Vesion
                        string[] ff = t.Split(',');
                        sourceVesion.Add(ff[0], ff[1]);
                    });
                List<string> lstUpdate = new List<string>();
                List<string> lstDelete = new List<string>();
                //获取最新版本的更新目录
                string rootUrl = Path.Combine(HttpRuntime.AppDomainAppPath,"Sys");
                string[] versions = Directory.GetDirectories(rootUrl);
                if (versions == null || versions.Length == 0)
                    return false;
                Version lastestVersion = new Version("1.0");
                string updateRoot = string.Empty;
                Array.ForEach(versions, t =>
                {
                    Version temp = new Version(Path.GetFileName(t));
                    if (temp > lastestVersion)
                    {
                        lastestVersion = temp;
                        updateRoot = t;
                    }
                });
                //获取更新内容
                string[] updateFilePaths = Directory.GetFiles(updateRoot);
                if (updateFilePaths == null || updateFilePaths.Length == 0)
                    return false;
                Array.ForEach(updateFilePaths, t =>
                    {
                        string tempFileName=Path.GetFileName(t);
                        //判断目前版本是否存在该文件
                        bool exits = sourceVesion.ContainsKey(tempFileName);
                        //判断是否需要更新
                        if (exits)
                        {
                            if (tempFileName.EndsWith("dll") || tempFileName.EndsWith("exe"))
                            {
                                Version oldVesion = new Version(sourceVesion[tempFileName]);
                                FileVersionInfo versionTemp = FileVersionInfo.GetVersionInfo(t);
                                Version newVesion = new Version(versionTemp.FileVersion);
                                if (newVesion > oldVesion)
                                {
                                    lstUpdate.Add(tempFileName);
                                }
                            }
                            sourceVesion.Remove(tempFileName);
                        }
                        else
                        {
                            lstUpdate.Add(tempFileName);
                        }
                    });

                //获取需要删除的文件
                foreach (var item in sourceVesion)
                {
                    lstDelete.Add(item.Key);
                }
                deleteFileLst = lstDelete.ToArray();

                //返回更新的内容
                List<byte[]> lst = new List<byte[]>();
                List<string> fileNames = new List<string>();
                foreach (string item in lstUpdate)
                {
                    string path = Path.Combine(updateRoot, item);
                    if (string.IsNullOrEmpty(item) || File.Exists(path) == false)
                        continue;
                    FileVersionInfo version = FileVersionInfo.GetVersionInfo(path);
                    using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
                    {
                        byte[] buffer = new byte[stream.Length];
                        stream.Read(buffer, 0, buffer.Length);
                        lst.Add(buffer);
                        fileNames.Add(item + ";" + version.FileVersion);
                    }
                }
                uploadFileLst = fileNames.ToArray();
                fileContent = lst.ToArray();
                return result;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

  客户端后台更新类库

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                //循环删除文件
                for (int deleteIndex = 0; deleteIndex < _deleteLst.Length; deleteIndex++)
                {
                    string deleteTemp = Path.Combine(Application.StartupPath, _deleteLst[deleteIndex]);
                    if (File.Exists(deleteTemp))
                        File.Delete(deleteTemp);
                    backgroundWorker1.ReportProgress(1, new int[] { deleteIndex, (deleteIndex + 1) * 100 / _deleteLst.Length });
                }

                //获取文件总大小
                long totalSize = 0;
                Array.ForEach(_fileContent, t => { totalSize += t.Length; });
                long currentSize = 0;

                //循环更新文件
                for (int uploadIndex = 0; uploadIndex < _fileLst.Length; uploadIndex++)
                {
                    string sourcePath = string.Empty;
                    string[] tempFile = _fileLst[uploadIndex].Split('\\');
                    //遍历文件夹,判断是否存在-不存在需要删除
                    for (int folderDeep = 0; folderDeep < tempFile.Length - 1; folderDeep++)
                    {
                        if (string.IsNullOrEmpty(sourcePath))
                            sourcePath = Path.Combine(Application.StartupPath, tempFile[folderDeep]);
                        else
                            sourcePath = Path.Combine(sourcePath, tempFile[folderDeep]);
                        if (Directory.Exists(sourcePath) == false)
                            Directory.CreateDirectory(sourcePath);
                    }

                    sourcePath = Path.Combine(Application.StartupPath, _fileLst[uploadIndex]);
                    if (File.Exists(sourcePath))
                        File.Delete(sourcePath);//删除要覆盖的文件

                    //开始写入新的文件
                    using (FileStream stream = new FileStream(sourcePath, FileMode.Append))
                    {
                        byte[] total = _fileContent[uploadIndex];
                        byte[] buffer = new byte[10240];  //10KB
                        long sCurrentSize = 0;
                        int piz = total.Length / buffer.Length;
                        for (int i = 0; i < piz; i++)
                        {
                            buffer = total.Skip(i * 10240).Take(buffer.Length).ToArray();
                            currentSize += buffer.Length;
                            sCurrentSize += buffer.Length;
                            stream.Write(buffer, 0, buffer.Length);
                            backgroundWorker1.ReportProgress((int)(currentSize * 100 / totalSize), new int[] { uploadIndex + _deleteLst.Length, (int)(sCurrentSize * 100 / total.Length) });
                        }
                        int left = total.Length % buffer.Length;
                        if (left > 0)
                        {
                            buffer = total.Skip(piz * 10240).Take(left).ToArray();
                            currentSize += buffer.Length;
                            stream.Write(buffer, 0, buffer.Length);
                            backgroundWorker1.ReportProgress((int)(currentSize * 100 / totalSize), new int[] { uploadIndex + _deleteLst.Length, 100 });
                        }
                    }
                }

                e.Result = null;
            }
            catch (Exception ex)
            {
                e.Result = ex.Message;
            }
        }

  更新完成之后,将更新代码的程序关闭,开启客户端主线程

            //关闭程序,开启主窗体
            System.Diagnostics.Process.Start(Path.Combine(Application.StartupPath, "商户资料管理系统.exe"));
            Application.Exit();

  

 

  • 源码

github

客户端安装程序   网盘提取码(meat)

 

posted @ 2018-08-29 14:32  comicwang  阅读(290)  评论(0编辑  收藏  举报