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 参数 -> 全局参数 /// /// 日志类申明 /// private static ClassLog classLog = new ClassLog(); /// /// 服务器更新文件集合 /// private string[] files = null; /// /// 本地预下载文件集合 /// private List listfiles = null; /// /// 服务器更新时间 /// 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 方法 -> 检查更新 /// /// 检测是否有更新 /// Mr.Cai /// 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; } /// /// 读取RecordUpdate.xml /// /// RecordUpdate.xml文件的路径 /// "key"的值 /// 返回"value"的值 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 ""; } /// /// 获取服务器端软件的更新日期 /// /// 服务器地址 /// 返回日期 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 方法 -> 获取文件列表并赋给全局变量 /// /// 获取文件列表并赋给全局变量 /// Mr.Cai /// 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 方法 -> 备份文件 /// /// 备份下载文件 /// Mr.Cai /// /// 下载序号 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 方法 -> 读取显示预下载文件 /// /// 读取显示待下载的文件 /// Mr.Cai /// private void ReadFilesList() { if (files != null) { listfiles = new List(); 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 方法 -> 启动线程下载文件 /// /// 下载文件 /// Mr.Cai /// 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 方法 -> 手动开始下载按钮事件 /// /// 开始下载按钮 /// Mr.Cai /// /// /// 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); } } /// /// 自定义数据显示委托 /// /// 显示的文字信息 /// 总的数据包大小 /// 已下载数据包大小 private delegate void DelShowArg(string _ShowInfo, int _SumSize, int _DownloadedSize); /// /// 显示下载进度信息 /// /// 文字信息 /// 总的数据包大小 /// 已下载大小 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 方法 -> 重启升级后的程序 /// /// 重启升级后的程序 /// Mr.Cai /// 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 方法 -> 无需更新程序,如果未启动直接启动程序 /// /// 无需更新程序,如果未启动直接启动程序 /// Mr.Cai /// 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 方法 -> 强制结束程序,刷新通知栏区域图标 /// /// 强制结束程序,刷新通知栏区域图标 /// 刷新通知栏区域图标 /// 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 方法 -> 正常关闭当前程序事务处理 /// /// Mr.Cai 正常关闭当前程序事务处理 /// private void WindowsClosing() { //任务栏区显示图标 this.ShowInTaskbar = false; //托盘区图标隐藏 notifyIcon1.Visible = false; //托盘区资源释放 notifyIcon1.Dispose(); //关闭所有 System.Environment.Exit(0); } #endregion #region 方法 -> 内存释放、资源回收 /// /// 内存释放、资源回收 /// Mr.Cai /// /// /// private void FileDownload_FormClosing(object sender, FormClosingEventArgs e) { classLog = null; files = null; listfiles = null; updatetime = null; GC.Collect();//静态资源置空、不强制提醒系统回收 } #endregion } }