/****************************** * 说明:自动更新类 * 创建人:龚宇超 * 创建日期:2018-02-09 * 修改人: * 修改日期: * 修改备注: * 版本:1.0.0.0 ******************************/ using System; using System.Collections.Generic; using System.Text; using System.Net; using System.Xml; using System.Xml.Serialization; using System.IO; using System.Windows.Forms; using System.Diagnostics; using System.Threading; namespace Lskj.AutoUpdate { /// /// 自动更新类 /// public class AutoUpdater : IAutoUpdater { private bool _isMes = false; private bool _needRestart; private bool _download; private bool _mainLoad; public Config _config; private List _downloadFileListTemp; private bool _rollbackCompleted = false; public AutoUpdater() { _config = new Config().LoadConfig(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConstModel.AUTOUPDATE_CONFIG)); _mainLoad = false; } public AutoUpdater(string updateURL, bool mainload = true, bool isMes = false,string UpdateNotes="") { string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConstModel.AUTOUPDATE_CONFIG); _config = new Config().LoadConfig(path); _config.ServerUrl = updateURL; _config.SaveConfig(path); _config.UpdateNotes = UpdateNotes; _mainLoad = mainload; _isMes = isMes; } /// /// 说明:移动文件 /// 创建人:龚宇超 /// 创建日期:2018-02-23 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The old path. /// The new path. private void MoveFolderToOld(string oldPath, string newPath) { Exception lastException = null; for (int i = 0; i < 10; i++) { try { if (File.Exists(oldPath) && File.Exists(newPath)) { System.IO.File.Copy(oldPath, newPath, true); } return; } catch (IOException ex) { lastException = ex; Thread.Sleep(500); } catch (UnauthorizedAccessException ex) { lastException = ex; Thread.Sleep(500); } } throw new IOException("文件可能仍被其他进程占用,重试后仍无法回滚:" + newPath, lastException); //if (!File.Exists(oldPath) || !File.Exists(newPath)) // return; //for (int i = 0; i < 5; i++) //{ // try // { // File.Copy(oldPath, newPath, true); // return; // } // catch // { // if (i < 4) // System.Threading.Thread.Sleep(1000); // } //} } /// /// 说明:开始下载 /// 创建人:龚宇超 /// 创建日期:2018-02-23 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The download list. private void StartDownload(List downloadList) { _rollbackCompleted = false; FrmProgress dp = new FrmProgress(downloadList, this); DialogResult result = dp.ShowDialog(); if (result != DialogResult.OK) { if (dp.IsUserCanceled) return; RollBack(); throw new Exception("更新未能完成,已尝试回滚。请确认主程序和相关客户端已关闭后重试。"); } _config.SaveConfig(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConstModel.AUTOUPDATE_CONFIG)); IniUtil.Write("ApplicationUpdateTime", DateTime.Now.ToString("yyyy-MM-dd HH:mm")); if (_needRestart) { Directory.Delete(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConstModel.TEMP_FOLDER_NAME), true); MessageBox.Show(ConstModel.UPDATE_RESTART, ConstModel.LS_TITLE_NAME, MessageBoxButtons.OK, MessageBoxIcon.Information); CommonUnitity.RestartApplication(); } } /// /// 说明:Xml 转换为下载集合 /// 创建人:龚宇超 /// 创建日期:2018-02-23 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The XML. /// Dictionary<System.String, RemoteFile>. private Dictionary ParseRemoteXml(string xml) { XmlDocument document = new XmlDocument(); //document.Load(xml); try { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(xml); request.Timeout = 10000; request.ReadWriteTimeout = 10000; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { using (Stream stream = response.GetResponseStream()) { document.Load(stream); } } } catch (WebException ex) { if (ex.Status == WebExceptionStatus.Timeout) { throw new Exception("连接超时:网络不稳定或服务器未响应。"); } throw new Exception("网络请求失败: " + ex.Message); } Dictionary list = new Dictionary(); foreach (XmlNode node in document.DocumentElement.ChildNodes) { string key = node.Attributes["path"].Value; if (!list.ContainsKey(key)) list.Add(key, new RemoteFile(node)); } return list; } /// /// 说明:更新 /// 创建人:龚宇超 /// 创建日期:2018-02-23 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// public void Update() { Dictionary listRemotFile = ParseRemoteXml(_config.ServerUrl); List downloadList = new List(); foreach (LocalFile file in _config.UpdateFileList) { if (listRemotFile.ContainsKey(file.Path)) { RemoteFile rf = listRemotFile[file.Path]; string v1 = rf.Verison; string v2 = file.Version; if (v1 != v2) { downloadList.Add(new DownloadFileInfo(rf.Url, rf.Path, rf.LastVer, rf.Size, rf.Verison)); file.Path = rf.Path; file.LastVer = rf.LastVer; file.Size = rf.Size; file.Version = rf.Verison; if (rf.NeedRestart) _needRestart = true; _download = true; } listRemotFile.Remove(file.Path); } } foreach (RemoteFile file in listRemotFile.Values) { downloadList.Add(new DownloadFileInfo(file.Url, file.Path, file.LastVer, file.Size, file.Verison)); _download = true; _config.UpdateFileList.Add(new LocalFile(file.Path, file.LastVer, file.Size, file.Verison)); if (file.NeedRestart) _needRestart = true; } _downloadFileListTemp = downloadList; if (_download) { ProcessManager op = new ProcessManager(); FrmMain dc = new FrmMain(downloadList, _config.UpdateNotes); //FrmMain dc = new FrmMain(downloadList); if ((downloadList.Count > 0) && (_mainLoad)) { DialogResult dlg = dc.ShowDialog(); if (dlg != DialogResult.OK) { return; } } if (_mainLoad) { op.StartUpdateProcess(_isMes); } else { StartDownload(downloadList); } } } /// /// 说明:回滚 /// 创建人:龚宇超 /// 创建日期:2018-02-23 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// public void RollBack() { RollBack(false); } public void RollBack(bool silent) { if (_rollbackCompleted || _downloadFileListTemp == null) return; _rollbackCompleted = true; foreach (DownloadFileInfo file in _downloadFileListTemp) { string tempUrlPath = CommonUnitity.GetFolderUrl(file); string oldPath = string.Empty; try { if (!string.IsNullOrEmpty(tempUrlPath)) { oldPath = Path.Combine(CommonUnitity.SystemBinUrl + tempUrlPath.Substring(1), file.FileName); } else { oldPath = Path.Combine(CommonUnitity.SystemBinUrl, file.FileName); } if (oldPath.EndsWith("_")) oldPath = oldPath.Substring(0, oldPath.Length - 1); MoveFolderToOld(oldPath + ".old", oldPath); } catch (Exception ex) { if (!silent) MessageBox.Show(ex.Message); } } } } }