2025-03-28 09:49:56 +08:00

699 lines
26 KiB
C#
Raw 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.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using FileDownload.Config;
using System.IO;
using System.Net;
using System.Xml.Linq;
using System.Globalization;
using System.Diagnostics;
using System.Threading;
using System.Xml;
namespace FileDownload
{
public partial class FileDownload : Form
{
public FileDownload()
{
InitializeComponent();
this.notifyIcon1.Visible = true;//在通知区显示Form的Icon
this.WindowState = FormWindowState.Minimized;
this.Visible = false;
this.ShowInTaskbar = false; //使Form不在任务栏上显示
}
#region ->
/// <summary>
/// 日志类申明
/// </summary>
private static ClassLog classLog = new ClassLog();
/// <summary>
/// 服务器更新文件集合
/// </summary>
private string[] files = null;
/// <summary>
/// 本地预下载文件集合
/// </summary>
private List<FilesInfo> listfiles = null;
/// <summary>
/// 服务器更新时间
/// </summary>
private string updatetime = null;
#endregion
#region -> Win窗口配置
//点击图标显示窗口
private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (WindowState == FormWindowState.Minimized)
{
//还原窗体显示
WindowState = FormWindowState.Normal;
//激活窗体并给予它焦点
this.Activate();
//任务栏区显示图标
this.ShowInTaskbar = true;
//托盘区图标
notifyIcon1.Visible = false;
}
}
//最小化隐藏窗口
private void Recorder_SizeChanged(object sender, EventArgs e)
{
//判断是否选择的是最小化按钮
if (WindowState == FormWindowState.Minimized)
{
//隐藏任务栏区图标
this.ShowInTaskbar = false;
//图标显示在托盘区
notifyIcon1.Visible = true;
}
}
private void notifyIcon1_MouseClick(object sender, MouseEventArgs e)
{
if (WindowState == FormWindowState.Minimized)
{
//还原窗体显示
WindowState = FormWindowState.Normal;
//激活窗体并给予它焦点
this.Activate();
//任务栏区显示图标
this.ShowInTaskbar = true;
//托盘区图标
notifyIcon1.Visible = false;
}
}
# endregion
#region -> Win首次启动
private void FileDownload_Load(object sender, EventArgs e)
{
KillExe(CommonHelper.GetKillAppList); //关闭程序集合
if (CheckUpdate()) //检查更新
{
LoadDownloadFileList(); //获取文件列表并赋给全局变量
DownloadFiles(); //启动线程下载文件
}
else
{
StartupProgram(); //无需更新程序,如果未启动直接启动程序
}
}
#endregion
#region ->
/// <summary>
/// 检测是否有更新
/// Mr.Cai
/// </summary>
private bool CheckUpdate()
{
string strUpdateURL = GetConfigValue(ConfigHelper.strUpdateXmlPath, "ConnectUrl"); //读取本地xml中配置的更新服务器的URL
string strLastUpdateDate = GetConfigValue(ConfigHelper.strUpdateXmlPath, "UpDate"); //读取本地xml中配置的最近一次更新日期
if (strUpdateURL.Substring(strUpdateURL.Length - 1) != "/") //如果配置的xml中URL没带最后一个反斜杠则加一下防止出错
{
strUpdateURL += "/";
}
string strTheUpdateDate = getTheLastUpdateTime(strUpdateURL); //获得更新服务器端的此次更新日期
if (!String.IsNullOrEmpty(strTheUpdateDate) && !String.IsNullOrEmpty(strLastUpdateDate))//日期都不为空
{
if (DateTime.Compare(
Convert.ToDateTime(strTheUpdateDate, CultureInfo.InvariantCulture),
Convert.ToDateTime(strLastUpdateDate, CultureInfo.InvariantCulture)) > 0) //字符转日期,并比较日期大小
{
updatetime = strTheUpdateDate;//服务器更新时间
return true; //本次更新日期 大于 最近一次更新日期,有更新,修改更新标记
}
}
else
{
if (String.IsNullOrEmpty(strLastUpdateDate))
{
updatetime = strTheUpdateDate;//服务器更新时间
return true;
}
}
return false;
}
/// <summary>
/// 读取RecordUpdate.xml
/// </summary>
/// <param name="path">RecordUpdate.xml文件的路径</param>
/// <param name="appKey">"key"的值</param>
/// <returns>返回"value"的值</returns>
internal static string GetConfigValue(string path, string appKey)
{
XmlDocument xDoc = new XmlDocument();
XmlNode xNode;
XmlElement xElem = null;
try
{
xDoc.Load(path);
xNode = xDoc.SelectSingleNode("//appSettings");
xElem = (XmlElement)xNode.SelectSingleNode("//add[@key=\"" + appKey + "\"]");
}
catch (Exception ex)
{
classLog.WriteLog(ClassLog.LogType.Error, "Source:{" + ex.Source + "}" +
" StackTrace:{" + ex.StackTrace + "}" + " Message:{" + ex.Message + "}");
}
if (xElem != null)
return xElem.GetAttribute("value");
else
return "";
}
/// <summary>
/// 获取服务器端软件的更新日期
/// </summary>
/// <param name="Dir">服务器地址</param>
/// <returns>返回日期</returns>
private static string getTheLastUpdateTime(string Dir)
{
string LastUpdateTime = "";
string AutoUpdaterFileName = Dir + ConfigHelper.strUpdateListXmlPath;
try
{
WebClient wc = new WebClient();
Stream sm = wc.OpenRead(AutoUpdaterFileName);
XmlTextReader xml = new XmlTextReader(sm);
while (xml.Read())
{
if (xml.Name == "UpdateTime")
{
LastUpdateTime = xml.GetAttribute("Date");
break;
}
}
xml.Close();
sm.Close();
}
catch (Exception ex)
{
classLog.WriteLog(ClassLog.LogType.Error, "Source:{" + ex.Source + "}" +
" StackTrace:{" + ex.StackTrace + "}" + " Message:{" + ex.Message + "}");
}
return LastUpdateTime;
}
#endregion
#region ->
/// <summary>
/// 获取文件列表并赋给全局变量
/// Mr.Cai
/// </summary>
private void LoadDownloadFileList()
{
string xmlPath = CommonHelper.strUpdateURL + ConfigHelper.strUpdateListXmlPath;
WebClient wc = new WebClient();
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
try
{
StringBuilder sb = new StringBuilder();
XDocument oXDoc = XDocument.Load(xmlPath);
System.Xml.Linq.XElement xeRoot = oXDoc.Root;
System.Xml.Linq.XElement xele = xeRoot.Element("UpdateFileList");
foreach (var ele in xele.Elements())
{
if (sb.Length == 0)
{
sb.Append(ele.Value);
}
else
{
sb.Append("," + ele.Value);
}
}
files = sb.ToString().Split(',');
}
catch (Exception ex)
{
ClassLog.WriteLog(ClassLog.LogType.Error.ToString(), ex.Message);
}
}
#endregion
#region ->
/// <summary>
/// 备份下载文件
/// Mr.Cai
/// </summary>
/// <param name="index">下载序号</param>
private void downloadFile(string curfilename, int index)
{
try
{
string _CurFileName = curfilename;
string _FileName = curfilename;
//如果对应的文件经过处理
if (_CurFileName.EndsWith(".rar"))
{
_FileName = _CurFileName.Substring(0, _CurFileName.LastIndexOf(".rar")); //不带后缀的路径和文件名
}
string StrCurReNamePath = _FileName.Substring(0, _FileName.LastIndexOf("\\") + 1);//文件路径
string _SysDateString = System.DateTime.Now.ToString("yyyyMMdd");
#region
//创建备份日期+更新文件目录
if (!Directory.Exists(ConfigHelper.strMainProDir + StrCurReNamePath)) //路径是否存在
{
CommonHelper.createMultipleFolders(ConfigHelper.strMainProDir, StrCurReNamePath); //创建时间目录
}
if (!Directory.Exists(ConfigHelper.strBackupPath + _SysDateString + StrCurReNamePath)) //路径是否存在
{
CommonHelper.createMultipleFolders(ConfigHelper.strBackupPath + _SysDateString, StrCurReNamePath); //创建时间目录
}
//备份对应的文件--
if (File.Exists(ConfigHelper.strMainProDir + _FileName))
{
//备份当前时间
if (File.Exists(ConfigHelper.strBackupPath + _SysDateString + _FileName))
{
File.Delete(ConfigHelper.strBackupPath + _SysDateString + _FileName);
}
try
{
File.Copy(ConfigHelper.strMainProDir + _FileName,
ConfigHelper.strBackupPath + _SysDateString + _FileName);
}
catch { }
//如果存在配置文件就不更新该文件、也不删除该文件
if (_FileName.Substring(_FileName.LastIndexOf("\\") + 1) == "Record.exe.config")
{
return;
}
//删除文件
if (File.Exists(ConfigHelper.strMainProDir + _FileName))
{
File.Delete(ConfigHelper.strMainProDir + _FileName);
}
}
#endregion
#region \Record\
FilesInfo fileone = new FilesInfo(
CommonHelper.strUpdateURL + ConfigHelper.strSevUpdateFilesUrl + _CurFileName.Replace('\\', '/'),
ConfigHelper.strMainProDir + _FileName, _FileName.Substring(_FileName.LastIndexOf("\\") + 1));
listfiles.Add(fileone);
#endregion
}
catch (Exception ex)
{
ClassLog.WriteLog(ClassLog.LogType.Error.ToString(), ex.Message);
}
}
#endregion
#region ->
/// <summary>
/// 读取显示待下载的文件
/// Mr.Cai
/// </summary>
private void ReadFilesList()
{
if (files != null)
{
listfiles = new List<FilesInfo>();
for (int i = 0; i < files.Length; i++)
{
downloadFile(files[i], i);
}
listView1.Items.Clear();
ListViewItem item = null;
foreach (FilesInfo file in listfiles)
{
item = new ListViewItem(new string[] { file.FileName, file.FileDownloadPath, file.FileSavePath });
listView1.Items.Add(item);
}
}
}
#endregion
#region -> 线
/// <summary>
/// 下载文件
/// Mr.Cai
/// </summary>
private void DownloadFiles()
{
ReadFilesList();//加载待下载的文件
Downloader download = new Downloader(listfiles);
download.DownloadStartingEvent += new Downloader.DelProInfoArg(download_DownloadStartingEvent);//事件订阅,开始下载
download.DownloadedEvent += new Downloader.DelProInfoArg(download_DownloadedEvent);//事件订阅,新获取了数据表,更新显示
download.DownloadEndEvent += new Downloader.DelProInfoArg(download_DownloadEndEvent);//事件订阅,一个文件下载完成
download.DownloadALLEnd += new Downloader.DeldownloadEndArg(download_DownloadALLEnd);//事件订阅,所有的下载任务结束
download.ErrorloadEvent += new Downloader.ErrorloadEndArg(download_Errorload);//事件订阅,错误信息记录
download.Start();
}
#endregion
#region ->
/// <summary>
/// 开始下载按钮
/// Mr.Cai
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnStart_Click(object sender, EventArgs e)
{
DownloadFiles(); //启动线程下载文件
}
#endregion
#region ->
void download_Errorload(FilesInfo _file, string _error)
{
ClassLog.WriteLog(ClassLog.LogType.Error.ToString(),
"错误信息:" + _error + "\r\n重要参数" + _file.ToString());
}
void download_DownloadALLEnd(bool _flag)
{
string error = string.Empty;
if (_flag)
{
if (!string.IsNullOrEmpty(updatetime))
{
try
{
DateTime.Parse(updatetime);
//更新本地xml
CommonHelper.setConfigValue(ConfigHelper.strUpdateXmlPath, "UpDate", updatetime);
}
catch (Exception ex)
{
ClassLog.WriteLog(ClassLog.LogType.Error.ToString(),
"更新本地xml失败" + ex.ToString());
}
}
error = "下载已结束!";
RestartProgram();//重启升级后的程序
}
else
{
error = "下载发现错误,已终止下载!";
}
if (this.InvokeRequired)
{
this.BeginInvoke(new DelShowArg(ShowDownloadingInfo), new object[] { error, 0, 0 });
}
else
{
ShowDownloadingInfo(error, 0, 0);
}
System.Environment.Exit(0);
}
void download_DownloadEndEvent(FilesInfo _file)
{
int Downloaded = (int)_file.DownloadedSize / 1024;
int ALLdownload = (int)_file.SumSize / 1024;
string strDownloadingInfo = string.Format("{0} 已下载完成!", _file.FileName);
if (this.InvokeRequired)
{
this.BeginInvoke(new DelShowArg(ShowDownloadingInfo), new object[] { strDownloadingInfo, ALLdownload, Downloaded });
}
else
{
ShowDownloadingInfo(strDownloadingInfo, ALLdownload, Downloaded);
}
}
void download_DownloadedEvent(FilesInfo _file)
{
int Downloaded = (int)_file.DownloadedSize / 1024;
int ALLdownload = (int)_file.SumSize / 1024;
string strDownloadingInfo = string.Format("{0} 正在下载中!", _file.FileName);
if (this.InvokeRequired)
{
this.BeginInvoke(new DelShowArg(ShowDownloadingInfo), new object[] { strDownloadingInfo, ALLdownload, Downloaded });
}
else
{
ShowDownloadingInfo(strDownloadingInfo, ALLdownload, Downloaded);
}
}
void download_DownloadStartingEvent(FilesInfo _file)
{
int Downloaded = (int)_file.DownloadedSize / 1024;
int ALLdownload = (int)_file.SumSize / 1024;
string strDownloadingInfo = string.Format("开始下载 {0}", _file.FileName);
if (this.InvokeRequired)
{
this.BeginInvoke(new DelShowArg(ShowDownloadingInfo), new object[] { strDownloadingInfo, ALLdownload, Downloaded });
}
else
{
ShowDownloadingInfo(strDownloadingInfo, ALLdownload, Downloaded);
}
}
/// <summary>
/// 自定义数据显示委托
/// </summary>
/// <param name="_ShowInfo">显示的文字信息</param>
/// <param name="_SumSize">总的数据包大小</param>
/// <param name="_DownloadedSize">已下载数据包大小</param>
private delegate void DelShowArg(string _ShowInfo, int _SumSize, int _DownloadedSize);
/// <summary>
/// 显示下载进度信息
/// </summary>
/// <param name="_ShowInfo">文字信息</param>
/// <param name="_SumSize">总的数据包大小</param>
/// <param name="_DownloadedSize">已下载大小</param>
private void ShowDownloadingInfo(string _ShowInfo, int _SumSize, int _DownloadedSize)
{
lblProInfo.Text = _ShowInfo;
if (_SumSize != 0 && _DownloadedSize != 0)
{
Probar.Maximum = _SumSize;
Probar.Minimum = 0;
Probar.Value = _DownloadedSize;
lblPercent.Text = string.Format("{0}%", _DownloadedSize * 100 / _SumSize);
}
}
#endregion
#region ->
/// <summary>
/// 重启升级后的程序
/// Mr.Cai
/// </summary>
private void RestartProgram()
{
Process[] _ProcessRecord = Process.GetProcessesByName("Record"); //系统日志程序
if (_ProcessRecord != null)
{
foreach (Process _Process in _ProcessRecord)
{
_Process.CloseMainWindow();
_Process.Kill();
_Process.Close();
}
}
try
{
Process exep = new Process();
exep.StartInfo.FileName = ConfigHelper.strMainProDir + "Record.exe";
exep.StartInfo.Arguments = "Record";
exep.StartInfo.CreateNoWindow = true;
exep.StartInfo.UseShellExecute = false;
exep.Start();
exep.WaitForExit(1000);//等待外部程序退出后才能往下低调执行
}
catch (Exception ex)
{
ClassLog.WriteLog(ClassLog.LogType.Error.ToString(), "程序启动报错:" + ex.Message);
}
//关闭当前程序
WindowsClosing();
}
#endregion
#region -> ,
/// <summary>
/// 无需更新程序,如果未启动直接启动程序
/// Mr.Cai
/// </summary>
private void StartupProgram()
{
Process[] _ProcessRecord = Process.GetProcessesByName("Record"); //系统日志程序
if (_ProcessRecord == null || _ProcessRecord.Length == 0)
{
try
{
Process exep = new Process();
exep.StartInfo.FileName = ConfigHelper.strMainProDir + "Record.exe";
exep.StartInfo.Arguments = "Record";
exep.StartInfo.CreateNoWindow = true;
exep.StartInfo.UseShellExecute = false;
exep.Start();
exep.WaitForExit(1000);//等待外部程序退出后才能往下低调执行
}
catch (Exception ex)
{
ClassLog.WriteLog(ClassLog.LogType.Error.ToString(),
"程序启动报错检查RecordUpdate.xml文件版本时间是不是和服务器时间一致导致未找到Record.exe文件" + ex.Message);
//在此重新更新程序,也可屏蔽底下代码不做操作
LoadDownloadFileList();//获取文件列表并赋给全局变量
DownloadFiles(); //启动线程下载文件
return;
}
}
//MessageBox.Show("I'm good, I don't need to be updated!");
//关闭当前程序
WindowsClosing();
}
#endregion
#region ->
private void KillExe(string[] strProNameList)
{
if (strProNameList == null)
{
return;
}
foreach (string strProName in strProNameList)
{
if (!string.IsNullOrEmpty(strProName))
{
Process[] processes = Process.GetProcessesByName(strProName.Substring(0, strProName.LastIndexOf('.'))); //同程序名的所有进程
foreach (Process p in processes)//判断当前进程中是否已有该程序
{
if (p.MainModule.ModuleName == strProName)//通过程序路径判断,而不能通过程序名判断
{
string strVN = p.MainModule.FileVersionInfo.FileVersion; //获取进程中正在运行的这个程序的版本号
p.Kill(); // 结束进程
}
}
}
}
RefreshNotifyIcon();
}
#endregion
#region ->
/// <summary>
/// 强制结束程序,刷新通知栏区域图标
/// 刷新通知栏区域图标
/// </summary>
private void RefreshNotifyIcon()
{
IntPtr vHandle = NotifyIconOverflowWindow();
IntPtr vProcessId = IntPtr.Zero;
Win32API.GetWindowThreadProcessId(vHandle, ref vProcessId);
IntPtr vProcess = Win32API.OpenProcess(Win32API.PROCESS_VM_OPERATION | Win32API.PROCESS_VM_READ | Win32API.PROCESS_VM_WRITE, IntPtr.Zero, vProcessId);
IntPtr vPointer = Win32API.VirtualAllocEx(vProcess, (int)IntPtr.Zero, 0x1000, Win32API.MEM_RESERVE | Win32API.MEM_COMMIT, Win32API.PAGE_READWRITE);
try
{
Rect r;
Win32API.GetWindowRect(vHandle, out r);
int width = r.Right - r.Left;
int height = r.Bottom - r.Top;
//从任务栏中间从左到右 MOUSEMOVE一遍所有图标状态会被更新
for (int x = 1; x < width; x++)
{
for (int y = 0; y < height; y += 4)
{
Win32API.SendMessage(vHandle, Win32API.WM_MOUSEMOVE, 0, MakeLParam(x, y));
}
}
}
finally
{
Win32API.VirtualFreeEx(vProcess, vPointer, 0, Win32API.MEM_RELEASE);
Win32API.CloseHandle(vProcess);
}
}
private IntPtr NotifyIconOverflowWindow()
{
IntPtr h = IntPtr.Zero;
IntPtr hTemp = IntPtr.Zero;
h = Win32API.FindWindow("NotifyIconOverflowWindow", null); //托盘容器
hTemp = Win32API.FindWindowEx(h, IntPtr.Zero, "ToolbarWindow32", null);
return hTemp;
}
private IntPtr MakeLParam(int LoWord, int HiWord)
{
return (IntPtr)((HiWord << 16) | (LoWord & 0xffff));
}
#endregion
#region ->
/// <summary>
/// Mr.Cai 正常关闭当前程序事务处理
/// </summary>
private void WindowsClosing()
{
//任务栏区显示图标
this.ShowInTaskbar = false;
//托盘区图标隐藏
notifyIcon1.Visible = false;
//托盘区资源释放
notifyIcon1.Dispose();
//关闭所有
System.Environment.Exit(0);
}
#endregion
#region ->
/// <summary>
/// 内存释放、资源回收
/// Mr.Cai
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void FileDownload_FormClosing(object sender, FormClosingEventArgs e)
{
classLog = null;
files = null;
listfiles = null;
updatetime = null;
GC.Collect();//静态资源置空、不强制提醒系统回收
}
#endregion
}
}