using ProjectBase.Data.Logs; using ProjectBase.Data.Zip; using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Linq; using System.Net; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Xml; using System.Xml.Serialization; namespace ProjectBase.Data.Update { /// /// 程序更新事件参数 /// public class ManifestEventArgs : EventArgs { public Manifest Manifest { get; set; } } /// /// 激活安装开始事件参数 /// public class ActivationStartedEventArgs : EventArgs { public Manifest Manifest { get; set; } public bool Cancel { get; set; } } /// /// 安装完成事件参数 /// public class ActivationCompletedEventArgs : AsyncCompletedEventArgs { public ActivationCompletedEventArgs(Exception error, bool cancelled, object userState) : base(error, cancelled, userState) { } public Manifest Manifest { get; set; } } /// /// 程序自动更新操作类,封装了文件下载、文件复制、文件解压等操作 /// public class UpdateClass { #region 变量属性 private DownloadClass downloader = new DownloadClass(); private FileCopyClass fileCopyer = new FileCopyClass(); private UpdaterConfigurationView updateCfgView = new UpdaterConfigurationView(); private string backupFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "../backup"); /// /// 封装的文件下载操作类 /// public DownloadClass Downloader { get { return downloader; } } /// /// 封装的文件复制操作类 /// public FileCopyClass FileCopyer { get { return fileCopyer; } } #endregion #region 事件 /// /// 下载进度 /// public event EventHandler DownloadProgressChanged; /// /// 下载完成事件 /// public event EventHandler DownloadCompleted; /// /// 下载错误触发的事件 /// public event EventHandler DownloadError; public event EventHandler ActivationInitializing; public event EventHandler ActivationCompleted; public event EventHandler ActivationStarted; public event EventHandler ActivationProgressChanged; public event EventHandler ActivationError; #endregion #region 下载更新实现 public UpdateClass() { downloader.DownloadCompleted += new EventHandler(downloader_DownloadCompleted); downloader.DownloadError += new EventHandler(downloader_DownloadError); downloader.DownloadProgressChanged += new EventHandler(downloader_DownloadProgressChanged); fileCopyer.FileCopyError += new EventHandler(fileCopyer_FileCopyError); fileCopyer.FileCopyCompleted += new EventHandler(fileCopyer_FileCopyCompleted); fileCopyer.FileCopyProgressChanged += new EventHandler(fileCopyer_FileCopyProgressChanged); } /// /// 是否有最新的版本 /// public bool HasNewVersion { get { var m = CheckForUpdates(); return m.Length > 0; } } /// /// 检查更新,返回更新清单列表 /// /// public Manifest[] CheckForUpdates() { updateCfgView.Refresh(); Uri uri = new Uri(updateCfgView.ManifestUri); string doc = DownLoadFile(uri, updateCfgView.ManifestName, updateCfgView.ManifestPasswd); XmlSerializer xser = new XmlSerializer(typeof(Manifest)); var manifest = xser.Deserialize(new XmlTextReader(doc, XmlNodeType.Document, null)) as Manifest; if (manifest == null || manifest.Version == updateCfgView.Version || manifest.MyApplication.ApplicationId != updateCfgView.ApplicationId) { return new Manifest[0]; } return new Manifest[] { manifest }; } /// /// 用于远程下载文件清单 /// /// 文件清单网络路径 /// private string DownLoadFile(Uri uri, string username, string password) { WebRequest request = WebRequest.Create(uri); request.Credentials = new NetworkCredential(username, password); string response = String.Empty; using (WebResponse res = request.GetResponse()) { using (StreamReader reader = new StreamReader(res.GetResponseStream(), true)) { response = reader.ReadToEnd(); } } return response; } /// /// 同步下载文件清单中的文件 /// /// 下载文件清单 public void Download(Manifest[] manifests) { foreach (var m in manifests) { downloader.Download(m); } } /// /// 异步下载文件清单中的文件 /// /// 下载文件清单 public void DownloadAsync(Manifest[] manifests) { foreach (var m in manifests) { downloader.DownloadAsync(m); } } /// /// 下载完毕后执行的启动操作 /// /// public void Activate(Manifest[] manifests) { foreach (var m in manifests) { OnActivationInitializing(new ManifestEventArgs() { Manifest = m }); Backup(m, downloader.TempPath); ActivationStartedEventArgs e = new ActivationStartedEventArgs() { Manifest = m }; OnActivationStarted(e); if (e.Cancel) { Clear(); break; } else { fileCopyer.CopyAsync(m, downloader.TempPath); } } } /// /// 备份操作 /// /// 文件清单 private void Backup(Manifest manifest, string sourcePath) { try { //string sourcePath = Path.GetFullPath(manifest.MyApplication.Location); string s_filename = string.Empty; string t_filename = string.Empty; if (!Directory.Exists(backupFilePath)) { Directory.CreateDirectory(backupFilePath); } foreach (var file in manifest.ManifestFiles.Files) { t_filename = Path.Combine(backupFilePath, file.Source); s_filename = Path.Combine(sourcePath, file.Source); if (File.Exists(s_filename)) { File.Copy(s_filename, t_filename, true); } } } catch (Exception ex) { LogHelper.log.Error("备份文件出现错误" + ex); } } /// /// 回滚文件下载内容 /// /// public void Rollback(Manifest manifest) { try { string filename = string.Empty; foreach (var file in manifest.ManifestFiles.Files) { filename = Path.Combine(backupFilePath, file.Source); File.Copy(filename, Path.Combine(Path.GetFullPath(manifest.MyApplication.Location), file.Source)); } //Directory.Delete(backupFilePath, true); } catch (Exception ex) { LogHelper.log.Error("回滚文件出现错误" + ex); } } /// /// 清除临时文件 /// private void Clear() { try { //Directory.Delete(backupFilePath, true); Directory.Delete(downloader.TempPath, true); } catch (Exception ex) { LogHelper.log.Error("清理临时文件出现错误" + ex); } } #endregion #region 事件处理 private void fileCopyer_FileCopyError(object sender, FileCopyErrorEventArgs e) { OnActivationError(e); } private void fileCopyer_FileCopyProgressChanged(object sender, FileCopyProgressChangedEventArgs e) { if (ActivationProgressChanged != null) { ActivationProgressChanged(sender, e); } } private void fileCopyer_FileCopyCompleted(object sender, FileCopyCompletedEventArgs e) { Clear(); try { //BackupSourceFiles(e.Manifest, updateCfgView.Version); updateCfgView.Version = e.Manifest.Version; } catch (Exception ex) { LogHelper.log.Info("备份原始程序出错误, 错误为." + ex); } if (ActivationCompleted != null) { ActivationCompletedEventArgs evt = new ActivationCompletedEventArgs(e.Error, e.Cancelled, e.UserState); evt.Manifest = e.Manifest; OnActivationCompleted(evt); } } /// /// 打包备份原始版本程序 /// /// private void BackupSourceFiles(Manifest manifest, string sourceVersion) { string folderFullName = new DirectoryInfo("../").FullName;//当前应用程序路径的上级目录 "../" + rootPath; DirectoryInfo TheFolder = new DirectoryInfo(folderFullName); foreach (DirectoryInfo NextFolder in TheFolder.GetDirectories()) { if (NextFolder.Name == manifest.MyApplication.Expand) { string sourceFiles = folderFullName + NextFolder.Name; string targetFiles = backupFilePath + "/" + NextFolder.Name + "_" + sourceVersion + ".zip"; ZipUtility.ZipFiles(sourceFiles, targetFiles, null); } } } private void downloader_DownloadProgressChanged(object sender, DownloadProgressEventArgs e) { if (DownloadProgressChanged != null) { DownloadProgressChanged(sender, e); } } private void downloader_DownloadError(object sender, DownloadErrorEventArgs e) { if (DownloadError != null) { DownloadError(sender, e); } } private void downloader_DownloadCompleted(object sender, DownloadCompleteEventArgs e) { if (DownloadCompleted != null) { DownloadCompleted(sender, e); } } private void OnActivationInitializing(ManifestEventArgs e) { if (ActivationInitializing != null) { ActivationInitializing(this, e); } } private void OnActivationStarted(ActivationStartedEventArgs e) { if (ActivationStarted != null) { ActivationStarted(this, e); } } private void OnActivationCompleted(ActivationCompletedEventArgs e) { if (ActivationCompleted != null) { ActivationCompleted(this, e); } } private void OnActivationError(FileCopyErrorEventArgs e) { if (ActivationError != null) { ActivationError(this, e); } } private void OnActivationProgressChanged(FileCopyProgressChangedEventArgs e) { if (ActivationProgressChanged != null) { ActivationProgressChanged(this, e); } } #endregion } }