using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; using System.Net; using System.Text; using System.Windows.Forms; namespace AutoUpdater { /// /// 后台静默下载升级包 /// public class BackDownload { private VersionObject vobject = null; private static string updatePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"update\"); public BackDownload(VersionObject vobject) { this.vobject = vobject; Downloading(); } private void Downloading() { try { var url = vobject.DfsAccessDomain + "/" + vobject.UploadFile; var downloadFileName = vobject.UploadFile.Substring(vobject.UploadFile.LastIndexOf('/') + 1); string dest = Path.Combine(updatePath, downloadFileName); //清空文件夹 DeleteFolder(updatePath); if (!Directory.Exists(updatePath)) Directory.CreateDirectory(updatePath); //写升级文件的校验信息 var md5FileName = Path.Combine(updatePath, string.Format("{0}.backCheck", vobject.CheckNum)); File.Create(md5FileName); //下载升级文件 //remove limits from service point manager ServicePointManager.MaxServicePoints = 10000; ServicePointManager.DefaultConnectionLimit = 10000; ServicePointManager.CheckCertificateRevocationList = true; ServicePointManager.Expect100Continue = false; ServicePointManager.MaxServicePointIdleTime = 1000 * 30; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls; ServicePointManager.UseNagleAlgorithm = false; ServicePointManager.DnsRefreshTimeout = 0; //提升系统外联的最大并发web访问数 ServicePointManager.DefaultConnectionLimit = 1024; ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; WebClient myWebClient = new WebClient(); myWebClient.DownloadFile(url, dest); } catch(Exception ex) { Logger.Log("静默下载发生异常:"+ ex.Message); } } /// /// 静默升级 /// public static bool BackUpload() { bool result = false; try { //判断是否有升级文件 var checkStatus = CheckFile(); if (!checkStatus.Item1) { //校验失败 result = false; } else { //校验成功 //判断主程序是否处于运行状态 if (IsAppInstanceExist(getProcessName())) { System.Diagnostics.Process[] startProcesses = System.Diagnostics.Process.GetProcessesByName(getProcessName()); foreach (System.Diagnostics.Process start in startProcesses) { start.Kill(); } } //程序延时2秒钟 System.Threading.Thread.Sleep(1000); //将update目录下的 压缩文件 解压 UnZip(updatePath); //清空文件夹 DeleteFolder(updatePath); //升级完成后,启动主程序 StartApplication(Global.Instance.StartApplication); result = true; } } catch(Exception ex) { Logger.Log("静默升级发生异常:"+ ex.Message); result = false; } return result; } private static void UnZip(string srcPath) { string[] fileList = Directory.GetFiles(srcPath); foreach (string file in fileList) { FileInfo fileInfo = new FileInfo(file); if (fileInfo.Extension.ToLower().Equals(".zip")) { ZipStorer zip = ZipStorer.Open(file, FileAccess.Read); List dir = zip.ReadCentralDir(); string path; bool result; foreach (ZipStorer.ZipFileEntry entry in dir) { path = Path.Combine(Application.StartupPath, entry.FilenameInZip); result = zip.ExtractFile(entry, path); } zip.Close(); if (fileInfo.Attributes.ToString().IndexOf("ReadOnly") != -1) fileInfo.Attributes = FileAttributes.Normal; File.Delete(file);//直接删除其中的文件 } } } /// /// 启动一个应用程序/进程 /// /// private static void StartApplication(string appFilePath) { string currentPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, appFilePath); if (File.Exists(currentPath)) { Process downprocess = new Process(); downprocess.StartInfo.FileName = appFilePath; downprocess.Start(); } } private static Tuple CheckFile() { Tuple result; try { string zipFile = null; string checkFile = null; if (!Directory.Exists(updatePath)) { result = new Tuple(false, "文件路径不存在", null); } else { foreach (string d in Directory.GetFiles(updatePath)) { if (File.Exists(d)) { FileInfo fi = new FileInfo(d); switch (fi.Extension.ToLower()) { case ".zip": { zipFile = d; } break; case ".backcheck": { checkFile = fi.Name; } break; } } } // if(string.IsNullOrEmpty(zipFile) || string.IsNullOrEmpty(checkFile)) { Logger.Log("未发现可静默升级的文件信息"); result = new Tuple(false, null, null); } else { //校验文件md5 var zipMd5Res = GetMD5HashFromFile(zipFile); if (zipMd5Res.Item1) { var checkNum = checkFile.Substring(0, checkFile.LastIndexOf(".")); if (checkNum.Equals(zipMd5Res.Item2)) { result = new Tuple(true, zipFile, checkFile); } else { result = new Tuple(false, zipFile, checkFile); } } else { result = new Tuple(false, zipMd5Res.Item2, null); } } } } catch(Exception ex) { Logger.Log("校验升级文件异常:" + ex.Message); result = new Tuple(false, "校验升级文件异常", null); } return result; } private static Tuple GetMD5HashFromFile(string fileName) { Tuple result; try { FileStream file = new FileStream(fileName, FileMode.Open); System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider(); byte[] retVal = md5.ComputeHash(file); file.Close(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < retVal.Length; i++) { sb.Append(retVal[i].ToString("x2")); } result = new Tuple(true, sb.ToString()); } catch (Exception ex) { Logger.Log("获取升级文件MD5值发生异常:"+ ex.Message); result = new Tuple(false, "获取升级文件MD5值发生异常"); } return result; } /// /// 获取进程名称,根据主程序名称 /// /// private static string getProcessName() { int processIndex = Global.Instance.StartApplication.LastIndexOf(@"."); string processName = Global.Instance.StartApplication.Substring(0, processIndex); return processName; } /// /// 监测目标应用程序是否启动 /// /// /// private static bool IsAppInstanceExist(string instanceName) { System.Diagnostics.Process[] startProcesses = System.Diagnostics.Process.GetProcessesByName(instanceName); if (startProcesses.Length >= 1) { return true; } return false; } /// /// 删除文件夹 /// /// private static void DeleteFolder(string dir) { if (Directory.Exists(dir)) { foreach (string d in Directory.GetFileSystemEntries(dir)) { if (File.Exists(d)) { FileInfo fi = new FileInfo(d); if (fi.Attributes.ToString().IndexOf("ReadOnly") != -1) fi.Attributes = FileAttributes.Normal; File.Delete(d);//直接删除其中的文件 } else DeleteFolder(d);//递归删除子文件夹 } Directory.Delete(dir);//删除已空文件夹 } } } }