|
|
|
|
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
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 下载器
|
|
|
|
|
/// </summary>
|
|
|
|
|
private FileDownloader downloader;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 下载状态
|
|
|
|
|
/// </summary>
|
|
|
|
|
private DownloadStatus status = DownloadStatus.Downloading;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 文件总大小
|
|
|
|
|
/// </summary>
|
|
|
|
|
private long totalSize = 0;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 最后文件大小
|
|
|
|
|
/// </summary>
|
|
|
|
|
long lastSize = 0;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 已经下载文件大小
|
|
|
|
|
/// </summary>
|
|
|
|
|
long completedSize = 0;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 是否取消下载
|
|
|
|
|
/// </summary>
|
|
|
|
|
private bool canceled = false;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 显示文本长度
|
|
|
|
|
/// </summary>
|
|
|
|
|
const int MAX_URL_LENGTH = 35;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 是否更新成功
|
|
|
|
|
/// </summary>
|
|
|
|
|
private bool isUpdateSuccess = false;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 执行数据下载
|
|
|
|
|
/// </summary>
|
|
|
|
|
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<Task>();
|
|
|
|
|
foreach (DownloadURL url in urls)
|
|
|
|
|
{
|
|
|
|
|
tasks.Add(Task.Factory.StartNew<Tuple<bool , long>>(() =>
|
|
|
|
|
{
|
|
|
|
|
bool progressKnown = false;
|
|
|
|
|
long size = DownloadData.GetFileSize(url.URL , out progressKnown);
|
|
|
|
|
|
|
|
|
|
return new Tuple<bool , long>(progressKnown , size);
|
|
|
|
|
}).ContinueWith((data) =>
|
|
|
|
|
{
|
|
|
|
|
Tuple<bool , long> 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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 下载处理
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
/// <param name="e"></param>
|
|
|
|
|
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 = "关闭";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 启动一个应用程序/进程
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="appFilePath"></param>
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取进程名称,根据主程序名称
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
private string getProcessName()
|
|
|
|
|
{
|
|
|
|
|
int processIndex = Global.Instance.StartApplication.LastIndexOf(@".");
|
|
|
|
|
|
|
|
|
|
string processName = Global.Instance.StartApplication.Substring(0 , processIndex);
|
|
|
|
|
|
|
|
|
|
return processName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 监测目标应用程序是否启动
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="instanceName"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 删除文件夹
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="dir"></param>
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 复制文件夹所有内容到目标文件夹
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="srcPath"></param>
|
|
|
|
|
/// <param name="aimPath"></param>
|
|
|
|
|
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<ZipStorer.ZipFileEntry> 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);//直接删除其中的文件
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|