You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

316 lines
11 KiB
C#

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
{
/// <summary>
/// 后台静默下载升级包
/// </summary>
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);
}
}
/// <summary>
/// 静默升级
/// </summary>
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<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);//直接删除其中的文件
}
}
}
/// <summary>
/// 启动一个应用程序/进程
/// </summary>
/// <param name="appFilePath"></param>
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<bool, string, string> CheckFile()
{
Tuple<bool, string, string> result;
try
{
string zipFile = null;
string checkFile = null;
if (!Directory.Exists(updatePath))
{
result = new Tuple<bool, string, string>(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<bool, string, string>(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<bool, string, string>(true, zipFile, checkFile);
}
else
{
result = new Tuple<bool, string, string>(false, zipFile, checkFile);
}
}
else
{
result = new Tuple<bool, string, string>(false, zipMd5Res.Item2, null);
}
}
}
}
catch(Exception ex)
{
Logger.Log("校验升级文件异常:" + ex.Message);
result = new Tuple<bool, string, string>(false, "校验升级文件异常", null);
}
return result;
}
private static Tuple<bool, string> GetMD5HashFromFile(string fileName)
{
Tuple<bool, string> 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<bool, string>(true, sb.ToString());
}
catch (Exception ex)
{
Logger.Log("获取升级文件MD5值发生异常:"+ ex.Message);
result = new Tuple<bool, string>(false, "获取升级文件MD5值发生异常");
}
return result;
}
/// <summary>
/// 获取进程名称,根据主程序名称
/// </summary>
/// <returns></returns>
private static 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 static bool IsAppInstanceExist(string instanceName)
{
System.Diagnostics.Process[] startProcesses = System.Diagnostics.Process.GetProcessesByName(instanceName);
if (startProcesses.Length >= 1)
{
return true;
}
return false;
}
/// <summary>
/// 删除文件夹
/// </summary>
/// <param name="dir"></param>
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);//删除已空文件夹
}
}
}
}