using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.IO.Compression; using System.Linq; using System.Net; using System.Runtime.Serialization.Formatters.Binary; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; namespace Muchinfo.MTPClient.Update { /// /// UpdateForm.xaml 的交互逻辑 /// public partial class UpdateForm : Window { public UpdateForm(string updateUrl ,UpdateInfo updateInfo) { InitializeComponent(); applictionUpdateUrl = updateUrl; updateInfos = updateInfo; this.Loaded += MainWindow_Loaded; this.bnt_Close.Click += bnt_Close_Click; this.MouseDown += new MouseButtonEventHandler(Window_MouseDown); //this.Closing += MainWindow_Closing; Application.Current.Exit += Current_Exit; } // private Queue _downList = new Queue(); const string Update_GetConfigEx = "获取配置文件异常"; const string APP_Updating = "应用程序正在更新..."; const string Update_NoNewFileDowm = "没有提供最新的文件下载"; const string Update_GetServiceFileEx = "获取服务器文件信息出错"; const string Update_NowDownFile = "正在下载文件"; const string Update_FileAllFinish = "全部下载完成"; private const string update_bakDir = "Update_bak"; private const string update_Dir = "Update"; private UpdateInfo updateInfos; private string applictionUpdateUrl; private WebClient webClient = null; /// /// 程序文件夹 /// private string localAppFolder = AppDomain.CurrentDomain.BaseDirectory; /// /// 更新文件夹 /// private string localUpdateFolder = AppDomain.CurrentDomain.BaseDirectory + update_Dir; /// /// 备份文件夹 /// private string localBackupFolder = AppDomain.CurrentDomain.BaseDirectory + update_bakDir; /// /// 消息提示 /// private string msg = string.Empty; /// /// 总下载数 /// private float totalCount = 0f; /// /// 当前下载数 /// private float totalCount_Completed = 0f; /// /// 下载状态 /// private bool isRunning = false; private Queue _downList = new Queue(); /// /// 下载列表 /// public Queue DownList { get { return _downList; } set { _downList = value; } } #region 私有方法 #region 下载线程 void MainWindow_Loaded(object sender, RoutedEventArgs e) { BackgroundWorker bw = new BackgroundWorker(); bw.DoWork += bw_DoWork; bw.RunWorkerCompleted += bw_RunWorkerCompleted; bw.RunWorkerAsync(); } void bw_DoWork(object sender, DoWorkEventArgs e) { try { if (File.Exists(AppDomain.CurrentDomain.BaseDirectory + "Client.Update.old.exe")) { File.Delete(AppDomain.CurrentDomain.BaseDirectory + "Client.Update.old.exe"); } if (updateInfos == null) return; if (updateInfos != null && updateInfos.UpdateFiles != null && !updateInfos.UpdateFiles.Any()) { System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() => { SetMessageText(Update_NoNewFileDowm); })); } } catch (Exception ex) { System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() => { SetMessageText(Update_GetServiceFileEx); })); } } void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (updateInfos != null && updateInfos.UpdateFiles != null && !updateInfos.UpdateFiles.Any()) { return; } DownLoad(); } #endregion #region WebClient下载 public void DownLoad() { webClient = new WebClient(); webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(webClient_DownloadProgressChanged); webClient.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(webClient_DownloadFileCompleted); //删除并且重新创建Update文件夹 if (Directory.Exists(localUpdateFolder)) { Directory.Delete(localUpdateFolder, true); } Directory.CreateDirectory(localUpdateFolder); this.totalCount = updateInfos.UpdateFiles.Count; foreach (var updateFile in updateInfos.UpdateFiles) { DownList.Enqueue(updateFile); } UpdateFile updateFileInfo = DownList.Dequeue(); totalCount_Completed++; this.msg = Update_NowDownFile + updateFileInfo.FilePath; SetMessageText(this.msg); string downloadfile= updateFileInfo.FilePath; if (updateInfos.IsCompress && !updateFileInfo.IsConfig) { downloadfile =downloadfile.Substring(0,downloadfile.LastIndexOf(updateFileInfo.Extension))+".gz"; ////下载压缩文件 downloadfile= downloadfile.Replace('\\','/'); } string localFileName = string.Format("{0}/{1}", localUpdateFolder, downloadfile); string remotefile = string.Format("{0}/{1}", applictionUpdateUrl, downloadfile); FileInfo fileInfo = new FileInfo(localFileName); if (!Directory.Exists(fileInfo.DirectoryName)) { Directory.CreateDirectory(fileInfo.DirectoryName); } //下载更新至本地 webClient.DownloadFileAsync(new Uri(remotefile), localFileName, updateFileInfo); isRunning = true; } //下载中途,进度条控制,百分比显示 void webClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) { float totalBytesToReceive = e.TotalBytesToReceive; float bytesReceived = e.BytesReceived; int progressPercentage = e.ProgressPercentage; msg = (e.UserState as UpdateFile).FilePath; System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() => { pbCurrent.Value = progressPercentage; tbCurrentControl.Text = (bytesReceived / totalBytesToReceive).ToString("0%"); })); } //下载完成 void webClient_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) { if (e.Error != null) { SetMessageText((e.UserState as UpdateFile).FilePath + e.Error.Message); isRunning = false; return; } try { if (!isRunning) { return; } //进度条控制,百分比显示 System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() => { pbTotal.Value = (100 / totalCount) * totalCount_Completed; tbControl.Text = (totalCount_Completed / totalCount).ToString("0%"); })); if (DownList.Count > 0) { UpdateFile updateFileInfo = DownList.Dequeue(); totalCount_Completed++; this.msg = Update_NowDownFile + updateFileInfo.FilePath; SetMessageText(this.msg); string downloadfile = updateFileInfo.FilePath; if (updateInfos.IsCompress && !updateFileInfo.IsConfig) { downloadfile = downloadfile.Substring(0, downloadfile.LastIndexOf(updateFileInfo.Extension)) + ".gz"; ////下载压缩文件 downloadfile = downloadfile.Replace('\\', '/'); } string localFileName = string.Format("{0}/{1}", localUpdateFolder, downloadfile); string remotefile = string.Format("{0}/{1}", applictionUpdateUrl, downloadfile); FileInfo fileInfo = new FileInfo(localFileName); if (!Directory.Exists(fileInfo.DirectoryName)) { Directory.CreateDirectory(fileInfo.DirectoryName); } webClient.DownloadFileAsync(new Uri(remotefile), localFileName, updateFileInfo); } else { //全部下载完成 SetMessageText(APP_Updating); BackUpdateFile(); ReplaceFiles(); CreateUpdateConfig(); SetMessageText(Update_FileAllFinish); isRunning = false; App.Current.Shutdown(); } } catch (Exception ex) { throw ex; } } /// /// 备份旧版本至bak /// private void BackUpdateFile() { try { if (Directory.Exists(localBackupFolder)) { Directory.Delete(localBackupFolder, true); } Directory.CreateDirectory(localBackupFolder); foreach (var item in updateInfos.UpdateFiles) { string tempItem = item.FilePath.Replace('/', '\\'); if (File.Exists(localAppFolder + tempItem)) { var directoryIndex = tempItem.LastIndexOf("\\", System.StringComparison.Ordinal); if (directoryIndex > 0) { var directory = item.FilePath.Substring(0, directoryIndex); Directory.CreateDirectory(localBackupFolder + "\\" + directory); } File.Copy(localAppFolder + tempItem, localBackupFolder + "\\" + tempItem, true); } } } catch (Exception ex) { throw ex; } } /// /// 下载更新的文件从Update覆盖到使用目录 /// private void ReplaceFiles() { try { foreach (var item in updateInfos.UpdateFiles) { //如果更新的是Muchinfo.MTPClient.Update,则先把源文件重命名,然后复制过去。最后删除重命名过的源文件 var isfileExists = File.Exists(localUpdateFolder + "\\" + item.FilePath) || File.Exists(localUpdateFolder + "\\" + item.FilePath.Replace(item.Extension, ".gz")); if (isfileExists) { if (item.FilePath == "Client.Update.exe") { File.Move(localAppFolder + item.FilePath, localAppFolder + "Client.Update.old.exe"); } var directoryIndex = item.FilePath.LastIndexOf("\\", System.StringComparison.Ordinal); if (directoryIndex > 0) { var directory = item.FilePath.Substring(0, directoryIndex); var direPath = localAppFolder + "\\" + directory; if (!Directory.Exists(direPath)) { Directory.CreateDirectory(direPath); } } if (updateInfos.IsCompress && !item.IsConfig) //解压文件 { var compressFile = localUpdateFolder + "\\" + item.FilePath.Replace(item.Extension,".gz") ; DeCompress(compressFile, localAppFolder + item.FilePath); } else { File.Copy(localUpdateFolder + "\\" + item.FilePath, localAppFolder + item.FilePath, true); } } } } catch (Exception ex) { throw ex; } } /// /// 对目标压缩文件解压缩,将内容解压缩到指定文件夹 /// /// 压缩文件 /// 解压缩目录 public static void DeCompress(string sourceName, string targetPath) { using (Stream source = File.OpenRead(sourceName)) { using (FileStream destination = new FileStream(targetPath, FileMode.Create, FileAccess.Write)) { using (GZipStream input = new GZipStream(source, CompressionMode.Decompress, true)) { byte[] bytes = new byte[4096]; int n; while ((n = input.Read(bytes, 0, bytes.Length)) != 0) { destination.Write(bytes, 0, n); } } destination.Flush(); destination.Close(); } } } /// /// 生成本地配置目录 /// private void CreateUpdateConfig() { var updateHelper = new UpdateHelper(); var updateInfo = updateHelper.CreateUpdateInfoFile(AppDomain.CurrentDomain.BaseDirectory, new string[] { update_bakDir, update_Dir }); var savePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, updateInfo.GetType().Name + ".xml"); updateHelper.SaveUpdateXml(updateInfo, savePath); } #endregion void Current_Exit(object sender, ExitEventArgs e) { if (webClient != null) { webClient.Dispose(); } if (updateInfos == null) { return; } //下载中途、完成后关闭Appliction程序 UpdateManage.RegisterChart(); ////图表更新 if (updateInfos.ReStart) { string appName = updateInfos.StartAppName; if (!string.IsNullOrEmpty(appName)) { string path = localAppFolder + appName; if (File.Exists(path)) { System.Diagnostics.Process.Start(path); } } } } void bnt_Close_Click(object sender, RoutedEventArgs e) { App.Current.Shutdown(); } private void Window_MouseDown(object sender, MouseButtonEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed) DragMove(); } private void SetMessageText(string text) { System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() => { this.tbMessage.Text = text; })); } #endregion } }