tijian_jichuang/Code/SmartUpdater/UpdateUI.cs
2025-02-20 11:54:48 +08:00

798 lines
25 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using EAS.Distributed;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using EAS.Security;
namespace EAS.Distributed
{
public partial class UpdateUI : System.Windows.Forms.Form
{
Thread updateThread = null;
Thread killThread = null;
DateTime lastTime = DateTime.MinValue;
DateTime sTime = DateTime.MinValue;
SmartConfig sc1 = null; //原有配置
SmartConfig sc2 = null; //新配置
IList<SmartFile> updateList = new List<SmartFile>();
IList<SmartFile> deleteList = new List<SmartFile>();
bool bComplete = false;
bool m_Kill = true;
public UpdateUI()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad (e);
if(XUpdate.Instance.Title.Length > 0)
this.Text = XUpdate.Instance.Title;
this.progressBar.Maximum = 0;
this.progressBar.Minimum = 0;
this.statusErrors.Text = "0个错误";
this.statusTasks.Text = "0个任务";
//1.开启升级线程。
this.updateThread = new Thread(new ThreadStart(this.AutoUpdate));
this.updateThread.Start();
#if DEBUG
using (TextLogger loggger = new TextLogger())
{
loggger.Debug(XUpdate.Instance.GetBaseDirectory());
}
#endif
//2.启动一线程,杀掉相关的应用进程。
this.killThread = new Thread(new ThreadStart(() =>
{
while (m_Kill)
{
string baseDirectory = XUpdate.Instance.GetBaseDirectory();
Process[] process = System.Diagnostics.Process.GetProcesses();
foreach (var item in process)
{
//A.本进程,跳过。
if (item.Id == Process.GetCurrentProcess().Id) //自已
{
continue;
}
bool exists = false;
#region //A2.进程名如果同引导程序,关闭之。
string pName = item.ProcessName;
if (pName.EndsWith("*32"))
{
pName = pName.Substring(0, pName.Length - 3).Trim();
}
#if DEBUG
using (TextLogger loggger = new TextLogger { Path = Path.Combine(baseDirectory, "logs"), FileName = "kill.log" })
{
loggger.Info(pName);
}
#endif
exists = string.Compare(Path.GetFileNameWithoutExtension(XUpdate.Instance.Application), item.ProcessName, true) == 0;
if (!exists)
{
exists = string.Compare(Path.GetFileName(XUpdate.Instance.Application), item.ProcessName, true) == 0;
}
#endregion
if (!exists)
{
#region dll
//B.求模块清单进程是否64位。
ProcessModuleCollection ProcessModule = null;
try
{
ProcessModule = item.Modules;
}
catch { }
if (ProcessModule != null)
{
List<ProcessModule> vList = new List<System.Diagnostics.ProcessModule>();
foreach (ProcessModule pModule in ProcessModule)
{
vList.Add(pModule);
}
try
{
vList.Add(item.MainModule);
}
catch { }
#region 32Kill
//2.判断需要Kill?
//凡加载了工作目录之中的文件的进程就强制中止。
foreach (ProcessModule pModule in vList) //循环扫描模块。
{
#region
string modueFile = string.Empty;
try
{
modueFile = pModule.FileName;
}
catch { }
#if DEBUG
//using (TextLogger loggger = new TextLogger { Path = Path.Combine(baseDirectory, "logs"), FileName = "kill.log" })
//{
// loggger.Info(modueFile);
//}
#endif
if (string.Compare(Path.GetDirectoryName(modueFile), baseDirectory, true) == 0)
{
exists = true;
break;
}
#endregion
}
#endregion
}
#endregion
}
if (exists) //执行Kill。
{
#region Kill
try
{
item.Kill();
}
catch (System.Exception exc)
{
#if DEBUG
using (TextLogger loggger = new TextLogger { Path = Path.Combine(baseDirectory, "logs"),FileName ="kill.log" })
{
loggger.Error(exc);
}
#endif
}
#endregion
}
}
//暂停100毫秒继续。
System.Threading.Thread.Sleep(50);
}
}));
killThread.Start();
}
bool CloseComplete
{
get
{
return this.checkCloseComplete.Checked;
}
set
{
this.checkCloseComplete.Checked = value;
}
}
#region UI通知
int progressMax = 0;
int progressPos = 0;
string _message = string.Empty;
bool _error = false;
void UpdateMessage(string message,bool error)
{
_message = message;
_error = error;
ChangeMessage();
}
void ChangeMessage()
{
try
{
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(this.ChangeMessage));
return;
}
this.statusMessage.Text = _message.Trim() + "...";
this.labelMessage.Text = _message.Trim() + "...";
ListViewItem item = null;
if (!_error)
{
item = this.listTasks.Items.Add(_message, 1);
this.statusTasks.Text = this.listTasks.Items.Count.ToString() + "个任务";
this.listTasks.Update();
}
else
{
string msg = _message.Replace("\n", "");
item = this.listErrors.Items.Add(_message, 0);
this.statusErrors.Text = this.listErrors.Items.Count.ToString() + "个错误";
this.listErrors.Update();
}
}
catch { }
}
void UpdateProgress(int pos,int total)
{
progressMax = total;
progressPos = pos;
ChangeProgress();
}
void ChangeProgress()
{
try
{
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(this.ChangeProgress));
return;
}
this.progressBar.Maximum = progressMax;
this.progressBar.Value = progressPos;
}
catch { }
}
void ShowClose()
{
try
{
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(this.ShowClose));
return;
}
this.btnCancel.Visible = false;
this.btnClose.Visible = true;
}
catch { }
}
#endregion
/// <summary>
/// 检测是否需要更新。
/// </summary>
/// <returns></returns>
bool CheckUpdate()
{
updateList.Clear();
//判断
if (!XUpdate.Instance.AllowUpdate)
{
this.UpdateMessage("系统不需要升级", true);
this.UpdateProgress(500,500);
this.bComplete = false;
return false;
}
if (XUpdate.Instance.Service == null)
{
try
{
XUpdate.GetService();
}
catch(System.Exception exc)
{
this.UpdateMessage("初始化服务参数出错,错误:" + exc.Message, false);
this.UpdateProgress(500,500);
this.bComplete = false;
return false;
}
}
if (XUpdate.Instance.Service == null)
{
this.bComplete = false;
return false;
}
//读本地文件。
string file = Path.Combine(XUpdate.Instance.GetBaseDirectory(), SmartConfig.DefaultConfgiFile);
if (File.Exists(file))
{
try
{
sc1 = XUpdate.LoadSmartAssemblyList();
lastTime = sc1.Time;
}
catch
{
this.UpdateProgress(500, 500);
this.bComplete = false;
return false;
}
}
//生成升级清单。
this.GenUpdateList();
bool update = this.updateList.Count>0;
if (!update)
{
this.UpdateMessage("系统已是最新版本", false);
string buffer = XUpdate.Instance.Service.GetSmartUpdateConfig();
sc2 = SmartConfig.LoadXML(buffer);
string configFile = Path.Combine(XUpdate.Instance.GetBaseDirectory(), SmartConfig.DefaultConfgiFile);
SmartConfig.Save(this.sc2, configFile);
this.UpdateProgress(500,500);
this.bComplete = true;
}
return update;
}
/// <summary>
/// 生成更新清单。
/// </summary>
/// <returns></returns>
void GenUpdateList()
{
updateList = new List<SmartFile>();
//A1.原有配置。
if (sc1 == null)
{
sc1 = new SmartConfig();
}
//B.下载新配置
try
{
string buffer = XUpdate.Instance.Service.GetSmartUpdateConfig();
sc2 = SmartConfig.LoadXML(buffer);
}
catch (System.Exception exc)
{
this.UpdateMessage("下载程序集清单出错,错误:" + exc.Message, true);
this.UpdateProgress(500,500);
return;
}
if (sc2 == null)
sc2 = new SmartConfig();
//X1.在远程之中循环,排除在本地清单之中并且时间没有变更的记录。
foreach (SmartFile item in sc2.Files)
{
var sFile = sc1.Files
.Where(p => string.Compare(p.FileName, item.FileName, true) == 0)
.FirstOrDefault();
if (sFile == null)
{
updateList.Add(item);
}
else if(sFile.Time!=item.Time)
{
updateList.Add(item);
}
}
//X2.在远程清单之中但是本地没有文件。
string baseDirectory = XUpdate.Instance.GetBaseDirectory();
foreach (SmartFile item in sc2.Files)
{
string descFile = Path.Combine(baseDirectory, item.FileName);
if (!File.Exists(descFile))
{
int count = updateList
.Where(p => string.Compare(p.FileName, item.FileName, true) == 0)
.Count();
if (count == 0)
{
updateList.Add(item);
}
}
}
}
/// <summary>
/// 生成删除清单。
/// </summary>
/// <remarks>
/// 删除不必要的文件,即如果服务端删除了某些文件客户段如何处理。
/// </remarks>
/// <returns></returns>
void GenDeleteList()
{
//添加服务程序集到一个Key-Value之中
Dictionary<string, SmartFile> smartFiles = new Dictionary<string, SmartFile>();
foreach (SmartFile item in sc2.Files)
{
if (!smartFiles.ContainsKey(item.FileName))
{
smartFiles.Add(item.FileName, item);
}
}
//求在本地清单之中,不在服务器清单之中的。
foreach (SmartFile item in sc1.Files)
{
if (!smartFiles.ContainsKey(item.FileName))
{
deleteList.Add(item);
}
}
}
/// <summary>
/// 下载文件。
/// </summary>
/// <param name="sf"></param>
void DownFile(SmartFile sf)
{
string downDirectory = XUpdate.Instance.GetDownDirectory();
if (!Directory.Exists(downDirectory))
Directory.CreateDirectory(downDirectory);
try
{
XUpdate.GetService();
byte[] buffer = XUpdate.Instance.Service.DownloadSmartFile(sf.FileName);
buffer = Compressor.Decompress(buffer);
string fileName = Path.Combine(downDirectory, sf.FileName);
//子文件夹的创建。
string xPath = Path.GetDirectoryName(fileName);
if (!Directory.Exists(xPath))
{
try
{
Directory.CreateDirectory(xPath);
}
catch { }
}
//写文件。
File.WriteAllBytes(fileName, buffer);
}
catch (System.Exception exc)
{
this.UpdateMessage("下载组件"+Path.GetFileName(sf.FileName)+"出错,错误:" + exc.Message, true);
return;
}
}
/// <summary>
/// 移动文件。
/// </summary>
void MoveFiles()
{
string downDirectory = XUpdate.Instance.GetDownDirectory();
string baseDirectory = XUpdate.Instance.GetBaseDirectory();
if (!Directory.Exists(downDirectory))
return;
//1.移动文件
foreach (SmartFile sf in this.updateList)
{
string sourceFile = Path.Combine(downDirectory, sf.FileName);
string descFile = Path.Combine(baseDirectory, sf.FileName);
//子文件夹的创建。
string xPath = Path.GetDirectoryName(descFile);
if (!Directory.Exists(xPath))
{
try
{
Directory.CreateDirectory(xPath);
}
catch { }
}
if (File.Exists(sourceFile) && File.Exists(descFile))
{
try
{
File.Delete(descFile);
}
catch { }
}
if (File.Exists(sourceFile))
{
string dt = Path.GetDirectoryName(descFile);
if (!Directory.Exists(dt))
try
{
Directory.CreateDirectory(dt);
}
catch { }
try
{
File.Move(sourceFile, descFile);
}
catch { }
}
}
//2.删除目录
string[] files = Directory.GetFiles(downDirectory, "*.*", SearchOption.AllDirectories);
foreach (string file in files)
{
try
{
File.Delete(file);
}
catch { }
}
files = Directory.GetDirectories(downDirectory, "*.*", SearchOption.AllDirectories);
foreach (string file in files)
{
try
{
Directory.Delete(file);
}
catch { }
}
if (Directory.Exists(downDirectory))
try
{
Directory.Delete(downDirectory);
}
catch { }
//3.删除文件
foreach (SmartFile sf in this.deleteList)
{
string descFile = Path.Combine(baseDirectory, sf.FileName);
if (File.Exists(descFile) &&
!sf.FileName.EndsWith("EAS.SmartUpdater.exe", StringComparison.CurrentCultureIgnoreCase) &&
!sf.FileName.EndsWith("update.ini", StringComparison.CurrentCultureIgnoreCase))
{
try
{
File.Delete(descFile);
}
catch { }
}
}
//写配置
string configFile = Path.Combine(XUpdate.Instance.GetBaseDirectory(), SmartConfig.DefaultConfgiFile);
SmartConfig.Save(this.sc2, configFile);
}
void OnDataTransmit(System.EventArgs e)
{
UpdateMessage("判断系统是否需要更新", false);
this.UpdateProgress(1, 500);
bool update = this.CheckUpdate();
if (!update)
{
return;
}
//检查需要更新的程序集
this.UpdateMessage("下载升级清单", false);
this.UpdateProgress(2, 500);
this.GenUpdateList();
this.GenDeleteList();
if (this.updateList.Count == 0 && this.deleteList.Count == 0)
{
this.UpdateMessage("没有需要更新的组件", false);
this.UpdateProgress(500, 500);
//写配置
string configFile = Path.Combine(XUpdate.Instance.GetBaseDirectory(), SmartConfig.DefaultConfgiFile);
SmartConfig.Save(this.sc2, configFile);
this.bComplete = true;
//终止Kill纯程
this.m_Kill = false;
System.Threading.Thread.Sleep(100);
//关闭
btnClose_Click(this.btnClose, e);
return;
}
#region //删除待升级文件。
foreach (var sf in this.updateList)
{
string vDirectory = XUpdate.Instance.GetBaseDirectory();
string vFile = Path.Combine(vDirectory, sf.FileName);
if (File.Exists(vFile) &&
!sf.FileName.EndsWith("EAS.SmartUpdater.exe", StringComparison.CurrentCultureIgnoreCase) &&
!sf.FileName.EndsWith("update.ini", StringComparison.CurrentCultureIgnoreCase))
{
try
{
File.Delete(vFile);
}
catch { }
}
}
#endregion
//检查需要更新的程序集
this.UpdateMessage("准备下载文件", false);
this.UpdateProgress(3, 500);
int xProgress = 5 * this.updateList.Count + 10;
int index = 1;
foreach (SmartFile sf in this.updateList)
{
this.UpdateMessage("准备下载" + Path.GetFileName(sf.FileName) + "", false);
this.DownFile(sf);
this.UpdateMessage(Path.GetFileName(sf.FileName) + "完成下载", false);
this.UpdateProgress(5 * index, xProgress);
index++;
}
//
this.UpdateMessage("准备更新系统", false);
this.MoveFiles();
this.UpdateProgress(xProgress - 5, xProgress);
if (sc2.StartEx.Length > 0)
{
string cmd = XUpdate.Instance.GetBaseDirectory() + " " + sc2.StartEx;
System.Diagnostics.Process.Start(cmd);
}
//终止Kill纯程
this.m_Kill = false;
System.Threading.Thread.Sleep(100);
this.UpdateMessage("升级完成", false);
this.UpdateProgress(xProgress, xProgress);
this.bComplete = true;
}
void AutoUpdate()
{
bComplete = false;
try
{
this.OnDataTransmit(new System.EventArgs());
if (this.checkCloseComplete.Checked)
{
//this.Close();
System.Windows.Forms.Application.Exit();
}
}
catch (System.Threading.ThreadAbortException abortExc)
{
this.UpdateMessage(abortExc.Message, true);
}
catch (System.Exception exc)
{
this.UpdateMessage(exc.Message, true);
}
finally
{
this.ShowClose();
}
}
private void btnDetails_Click(object sender, System.EventArgs e)
{
if(this.buttonDetails.Text == "<< 详细")
{
this.buttonDetails.Text = "详细 >>";
this.tabControl.Visible = false;
this.Height = this.Height - this.tabControl.Height;
}
else
{
this.buttonDetails.Text = "<< 详细";
tabControl.Visible = true;
this.Height = this.Height + this.tabControl.Height;
}
}
private void btnCancel_Click(object sender, System.EventArgs e)
{
this.btnCancel.Enabled = false;
Cursor = Cursors.WaitCursor;
try
{
this.updateThread.Abort();
}
catch { }
this.m_Kill = false;
System.Threading.Thread.Sleep(100);
Cursor = Cursors.Default;
this.UpdateMessage("操作被取消", true);
this.btnClose.Visible = true;
tabControl.SelectedIndex = 1;
}
private void btnClose_Click(object sender, System.EventArgs e)
{
this.m_Kill = false;
System.Threading.Thread.Sleep(100);
if (this.bComplete)
{
if (this.updateList.Count >= 1)
{
MessageBox.Show(this, "系统升级完成,共升级了" + this.updateList.Count + "个应用程序模块,应用程序将重新启动!", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
Thread m_StartThread = new Thread(new ThreadStart(() =>
{
try
{
System.Diagnostics.Process.Start(XUpdate.Instance.Application);
}
catch { }
}));
m_StartThread.Start();
}
//this.Close();
System.Windows.Forms.Application.Exit();
}
private void listErrors_SelectedIndexChanged(object sender, System.EventArgs e)
{
if(this.listErrors.SelectedItems.Count > 0)
{
this.textError.Text = this.listErrors.SelectedItems[0].Text;
}
else
{
this.textError.Text = string.Empty;
}
}
private void UpdateUI_Load(object sender, EventArgs e)
{
}
}
}