using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Net; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace AutoUpdater { public enum DownloadStatus { Downloading, Completed, Failed, Canceled } public partial class Downloading : Form { /// /// 下载器 /// private FileDownloader downloader; /// /// 下载状态 /// private DownloadStatus status = DownloadStatus.Downloading; /// /// 文件总大小 /// private long totalSize = 0; /// /// 最后文件大小 /// long lastSize = 0; /// /// 已经下载文件大小 /// long completedSize = 0; /// /// 是否取消下载 /// private bool canceled = false; /// /// 显示文本长度 /// const int MAX_URL_LENGTH = 35; /// /// 是否更新成功 /// private bool isUpdateSuccess = false; /// /// 执行数据下载 /// delegate void DownloaderProgress(object sender); public Downloading() { InitializeComponent(); //按钮切换 this.btnPause.Tag = "Pause"; //初始化文件下载 downloader = new FileDownloader(); } protected override void OnLoad(EventArgs e) { base.OnLoad(e); //删除下载目录信息 DeleteFolder(Global.Instance.DownloadPath); //版本信息 this.lblVersion.Text = string.Format(this.lblVersion.Text , Global.Instance.NewVersion); //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; Task.Factory.StartNew(() => { this.DoStartDownload(this); }); } private void DoStartDownload(object sender) { try { this.Invoke(new DownloaderProgress(this.downloaderProgress) , new object[] { sender }); Application.DoEvents(); } catch (InvalidOperationException ex) //不建议使用该方法,目前尚未有效解决 { ExceptionUtils.Current.Handle(ex); } } private void downloaderProgress(object sender) { try { DownloadURLCollection urls = Global.Instance.Urls; var tasks = new List(); foreach (DownloadURL url in urls) { tasks.Add(Task.Factory.StartNew>(() => { bool progressKnown = false; long size = DownloadData.GetFileSize(url.URL , out progressKnown); return new Tuple(progressKnown , size); }).ContinueWith((data) => { Tuple value = data.Result; url.Size = value.Item2; this.totalSize += value.Item2; })); } Task.WaitAll(tasks.ToArray()); this.prgOverall.PositionMax = this.totalSize; downloader.ProgressChanged += new DownloadProgressHandler(downloader_ProgressChanged); long fileSizes = 0; foreach (DownloadURL url in urls) { if (!canceled) { lastSize = 0; Uri uri = new Uri(url.URL); string fileName = uri.Segments[uri.Segments.Length - 1].ToString(); this.prgCurrent.PositionMax = url.Size; if (url.Destination == string.Empty) { url.Destination = FileDownloader.DownloaderTempDirectory; } downloader.Download(url.URL , url.Destination); if (canceled) { break; } fileSizes += url.Size; this.Invoke(new MarshalProgress(MarshaledProgressChanged) , new object[] { null , new DownloadEventArgs(this.totalSize , url.Size) }); this.prgOverall.Position = fileSizes; completedSize = fileSizes; } } this.Invoke(new CompletedDelegate(this.MarshalDownloadComplete)); } catch (Exception ex) { ExceptionUtils.Current.Handle(ex); } } /// /// 下载处理 /// /// /// delegate void MarshalProgress(object sender , DownloadEventArgs e); private void downloader_ProgressChanged(object sender , DownloadEventArgs e) { this.Invoke(new MarshalProgress(this.MarshaledProgressChanged) , new object[] { sender , e }); } string lastPercent = string.Empty; private void MarshaledProgressChanged(object sender , DownloadEventArgs e) { try { this.prgCurrent.Position = (int)e.CurrentFileSize; if (e.CurrentFileSize == this.lastSize) { return; } this.prgOverall.Position += (e.CurrentFileSize - this.lastSize); this.completedSize += (e.CurrentFileSize - this.lastSize); this.lastSize = e.CurrentFileSize; if (e.TotalFileSize > 1024)//以K为单位 { this.lblCurrentComplete.Text = e.CurrentFileSize / 1024 + "K / " + e.TotalFileSize / 1024 + "K"; } else//小于K { this.lblCurrentComplete.Text = e.CurrentFileSize + "B / " + e.TotalFileSize + "B"; } this.prgCurrent.Text = ((int)((((double)e.CurrentFileSize) / e.TotalFileSize) * 100)).ToString() + "%"; this.prgOverall.Text = ((int)((((double)completedSize) / totalSize) * 100)).ToString() + "%"; if (this.prgOverall.Text != lastPercent) { int index = Text.IndexOf(" ("); if (index > -1) { this.Text = this.Text.Substring(0 , index); } this.Text += " (" + this.prgOverall.Text + ")"; lastPercent = this.prgOverall.Text; } Application.DoEvents(); } catch (Exception ex) { ExceptionUtils.Current.Handle(ex); } } private delegate void CompletedDelegate(); private void MarshalDownloadComplete() { if (this.totalSize == this.completedSize) { this.status = DownloadStatus.Completed; //暂停功能无效 this.btnPause.Visible = false; //窗体关闭功能无效 //关闭按钮无效 this.btnCancel.Enabled = false; //判断主程序是否处于运行状态 if (this.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(Global.Instance.DownloadPath); this.canceled = true; this.isUpdateSuccess = true; if (chkAutoClose.Checked) { //升级完成后,启动主程序 this.StartApplication(Global.Instance.StartApplication); this.Close(); } else { //窗体关闭功能生效 //关闭按钮生效 this.btnCancel.Enabled = true; this.btnCancel.Text = "关闭"; } } } /// /// 启动一个应用程序/进程 /// /// private 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 string getProcessName() { int processIndex = Global.Instance.StartApplication.LastIndexOf(@"."); string processName = Global.Instance.StartApplication.Substring(0 , processIndex); return processName; } /// /// 监测目标应用程序是否启动 /// /// /// private bool IsAppInstanceExist(string instanceName) { System.Diagnostics.Process[] startProcesses = System.Diagnostics.Process.GetProcessesByName(instanceName); if (startProcesses.Length >= 1) { return true; } return false; } private void btnPause_Click(object sender , System.EventArgs e) { if (this.btnPause.Tag.ToString() == "Pause") { downloader.Pause(); this.btnPause.Text = "继续"; this.btnPause.Tag = "Resume"; } else if (this.btnPause.Tag.ToString() == "Resume") { downloader.Resume(); this.btnPause.Text = "暂停"; this.btnPause.Tag = "Pause"; } } private void btnCancel_Click(object sender , System.EventArgs e) { if (!canceled) { downloader.Cancel(); this.status = DownloadStatus.Canceled; this.btnCancel.Text = "关闭"; this.btnPause.Visible = false; //删除下载文件夹 DeleteFolder(Global.Instance.DownloadPath); canceled = true; } else { if (isUpdateSuccess) { //升级完成后,启动主程序 this.StartApplication(Global.Instance.StartApplication); } this.Close(); } } /// /// 删除文件夹 /// /// private 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);//删除已空文件夹 } } ////不推荐使用,可能影响其他 //private void KillProcess() //{ // Process[] procList = Process.GetProcesses(); // for (int i = 0; i < procList.Length; i++) // { // switch (procList[i].ProcessName) // { // case "AutoUpdater": // procList[i].Kill(); // procList[i].Close(); // break; // } // } //} private void Downloading_FormClosed(object sender , FormClosedEventArgs e) { downloader.Cancel(); this.status = DownloadStatus.Canceled; //删除下载文件夹 DeleteFolder(Global.Instance.DownloadPath); canceled = true; System.Diagnostics.Process currentProcess = System.Diagnostics.Process.GetCurrentProcess(); currentProcess.Kill(); } /// /// 复制文件夹所有内容到目标文件夹 /// /// /// private void CopyDirectory(string srcPath , string aimPath) { //检查目标目录是否以目录分割字符结束如果不是则添加之 if (aimPath[aimPath.Length - 1] != Path.DirectorySeparatorChar) aimPath += Path.DirectorySeparatorChar; //判断目标目录是否存在如果不存在则新建之 if (!Directory.Exists(aimPath)) Directory.CreateDirectory(aimPath); //得到源目录的文件列表,该里面是包含文件以及目录路径的一个数组 //如果你指向copy目标文件下面的文件而不包含目录请使用下面的方法 //string[] fileList = Directory.GetFiles(srcPath); string[] fileList = Directory.GetFileSystemEntries(srcPath); //遍历所有的文件和目录 foreach (string file in fileList) { //先当作目录处理如果存在这个目录就递归Copy该目录下面的文件 if (Directory.Exists(file)) CopyDirectory(file , aimPath + Path.GetFileName(file)); //否则直接Copy文件 else File.Copy(file , aimPath + Path.GetFileName(file) , true); } } private 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);//直接删除其中的文件 } } } } }