using System; using System.Collections.Generic; using System.ComponentModel; using System.Text; using System.Threading; using System.Net; using System.IO; using System.Windows.Forms; using System.Reflection; using ryCommon; //在线升级类 namespace LiveUpdate { /// /// /// public class ClsLiveUpdate { /// /// 升级地址 /// public string UpdateUrl = ""; //升级地址 private double SoftVer = 0; //软件版本 private double ReVer = 0; //软件修正版本 private string SoftDate = "";//软件日期 private string SoftUpdateDes = "";//软件更新描述 private string SoftUpdateDesUrl = "";//软件更新描述Url private double DataVer = 0;//数据库版本 private string DataDate = "";//数据库日期 private string DataUpdateDes = "";//数据库更新描述 private string FileUpdateUrl = "";//文件更新地址 private string FileVerUpdateUrl = "";//针对文件版本不同使用不同下载地址 private string DbUpdateUrl = "";//数据库更新地址 /// /// /// public string CurUserId = "";//当前用户id /// /// 隔多久后再次检查更新 /// private int UpdateAfterTime =0; /// /// 本地保存的配置信息 /// public string SettingPath = "";//设置地址 /// /// 当前安装的软件版本 /// public double MySoftVer = 0; //软件版本 /// /// 当前安装的软件修正版本 /// public double MySoftRVer = 0; //软件修正版本 /// /// 当前安装的数据库版本 /// public double MyDataVer = 0;//数据库版本 /// /// /// public string SaveFileName = "tmp.tmp";//下载的文件保存文件 /// /// /// public string DownUrl = "";//下载地址 /// /// /// public bool isExit = false; private UpdateInfo m_UpdateType; /// /// 获取当前更新的类型 /// public UpdateInfo UpdateType { get { return m_UpdateType; } } /// /// 每隔n小时检测一次更新 /// public int UpdateLoopHours =0;//每隔n小时检测一次 private delegate void dd1(bool message); private Thread threadOne; /// /// 读取版本信息完成后激发 /// [Description("读取版本信息完成后激发")] public event EventHandler OnReadComplete; /// /// 没有版本更新时激发 /// [Description("没有版本更新时激发")] public event EventHandler OnNoUpdate; /// /// 发现新版本时激发 /// [Description("发现新版本时激发")] public event UpdateHandler OnUpdateComplete; /// /// 发生错误后激发 /// [Description("发生错误后激发")] public event ErrorHandler OnHappenError; /// /// 更新进度变化后激发 /// [Description("更新进度变化后激发")] public event LiveUpdate.LiveUpdateProgressChanged ProgressChanged; private LiveUpdate.LiveUpdateEventArgs _LiveUpdateEventArgs = new LiveUpdate.LiveUpdateEventArgs(); /// /// 开始检测新版本 /// public void StartLiveUpdate() //开始升级 { if (threadOne != null) { threadOne.Abort(); } threadOne = new Thread(new ThreadStart(GetVerInfo)); threadOne.SetApartmentState(ApartmentState.STA); threadOne.IsBackground = true; threadOne.Start(); } /// /// /// public Form ParentForm = null; /// /// 初始化升级函数 /// /// 为null,则表示事件运行在多线程模式下,否则,事件是在窗体所在线程下 public ClsLiveUpdate(Form ower) { ParentForm = ower; MySoftVer = AssemblyVersion; MySoftRVer = AssemblyReVersion; SettingPath = Application.StartupPath + @"\cUpdate.dat"; MyDataVer = 0; } /// /// /// public double AssemblyVersion { get { System.Diagnostics.FileVersionInfo info = System.Diagnostics.FileVersionInfo.GetVersionInfo(Application.ExecutablePath); string[] ver_item = info.ProductVersion.Split('.'); if (ver_item.Length == 4) { return Convert.ToDouble(ver_item[0]+"."+ver_item[1]); } else { return Convert.ToDouble(info.ProductMajorPart + "." + info.ProductMinorPart); } } } /// /// /// public double AssemblyReVersion { get { System.Diagnostics.FileVersionInfo info = System.Diagnostics.FileVersionInfo.GetVersionInfo(Application.ExecutablePath); string[] ver_item = info.ProductVersion.Split('.'); if (ver_item.Length == 4) { return Convert.ToDouble(ver_item[2] + "." + ver_item[3]); } else { return Convert.ToDouble(info.ProductBuildPart.ToString() + "." + info.ProductPrivatePart); } } } private void OnNoUpdate_T() { if (ParentForm != null) { ParentForm.Invoke(new Action(() => { OnNoUpdate?.Invoke(this, new EventArgs()); })); } else { OnNoUpdate?.Invoke(this, new EventArgs()); } } private void OnReadComplete_T() { if (ParentForm != null) { ParentForm.Invoke(new Action(() => { OnReadComplete?.Invoke(this, new EventArgs()); })); } else { OnReadComplete?.Invoke(this, new EventArgs()); } } private void OnUpdateComplete_T(UpdateInfo e) { if (ParentForm != null) { ParentForm.Invoke(new Action(() => { OnUpdateComplete?.Invoke(e); })); } else { OnUpdateComplete?.Invoke(e); } } private void OnHappenError_T(UpdateErrorInfo e) { if (ParentForm != null) { ParentForm.Invoke(new Action(() => { OnHappenError?.Invoke(e); })); } else { OnHappenError?.Invoke(e); } } /// /// 获取版本信息 /// private void GetVerInfo() //获取版本信息 { #region 读取本地配置,判断是否需要更新 ryCommon.Storage MyXml2 = new ryCommon.Storage(); int iResult = 0; MyXml2.LoadFromFile(SettingPath); MyXml2.SelectNode("id", "UpdateAfterTime"); UpdateAfterTime = MyXml2.GetAttrValue("Value", 0); DateTime LastUpdateTime; MyXml2.SelectNode("id", "LastUpdateTime"); LastUpdateTime =MyXml2.GetAttrValue("Value", Convert.ToDateTime("2011-01-01")); if (UpdateLoopHours > 0) { if ((DateTime.Now - LastUpdateTime).TotalHours.ToInt() < UpdateLoopHours) { OnNoUpdate_T(); return; } } if (UpdateAfterTime > 0) { if ((DateTime.Now.Date - LastUpdateTime.Date).Days < UpdateAfterTime) { OnNoUpdate_T(); return; } } MyXml2.SelectNode2("id", "LastUpdateTime"); MyXml2.SetAttrValue("Value", DateTime.Now.ToString()); MyXml2.SaveToFile(SettingPath); #endregion ryCommon.Storage MyXml = new ryCommon.Storage(); UpdateErrorInfo UpdateError; iResult=MyXml.LoadFromFile(UpdateUrl); if (iResult == 0) { UpdateError.ErrorId = 2; UpdateError.ErrorStr = "更新错误,读取远程文件失败"; OnHappenError_T(UpdateError); OnNoUpdate_T(); MyXml.LoadFromXMLText(""); return; } string SoftVersion = "未知"; //软件版本 MyXml.SelectNode2("id", "SoftVer"); RySoft.GetVerByVerStr(MyXml.GetAttrValue("Value", "0"), out SoftVer, out ReVer); //SoftVer = ConvertDouble(MyXml.GetAttrValue("Value","0"),0); SoftVersion=MyXml.GetAttrValue("Value","0"); //数据库版本 MyXml.SelectNode2("id", "DataVer"); DataVer = MyXml.GetAttrValue("Value", 0d); //软件更新地址 MyXml.SelectNode2("id", "FileUpdateUrl"); FileUpdateUrl = MyXml.GetAttrValue("Value", ""); //软件版本更新地址 MyXml.SelectNode2("id", "FileVerUpdateUrl"); FileVerUpdateUrl = MyXml.GetAttrValue("Value", ""); //数据库更新地址 MyXml.SelectNode2("id", "DbUpdateUrl"); DbUpdateUrl = MyXml.GetAttrValue("Value", ""); //软件日期 MyXml.SelectNode2("id", "SoftDate"); SoftDate = MyXml.GetAttrValue("Value", ""); //数据库日期 MyXml.SelectNode2("id", "DataDate"); DataDate = MyXml.GetAttrValue("Value", ""); //软件更新描述 MyXml.SelectNode2("id", "SoftUpdateDes"); SoftUpdateDes = MyXml.GetAttrValue("Value", ""); //软件更新描述Url MyXml.SelectNode2("id", "SoftUpdateDesUrl"); SoftUpdateDesUrl = MyXml.GetAttrValue("Value", ""); //数据库更新描述 MyXml.SelectNode2("id", "DataUpdateDes"); DataUpdateDes = MyXml.GetAttrValue("Value", ""); //设置 MyXml.SelectNode2("id", "SettingXML"); string SettingXML = MyXml.GetAttrValue("Value", ""); //在下载升级包前首先要下载的内容 MyXml.SelectNode2("id", "FirstDownList"); string FirstDownList = MyXml.GetAttrValue("Value", ""); //允许更新的用户列表 MyXml.SelectNode2("id", "UpdateUserList"); string m_UpdateUserList ="|"+ MyXml.GetAttrValue("Value", "").Replace(";","|")+"|"; if (MyXml.GetAttrValue("Value", "") == "") { m_UpdateUserList = ""; } //激发事件 OnReadComplete_T(); //更新标志,1表示软件更新,2表示数据库更新 int UpdateMarket = 0;//更新标志 UpdateInfo myUpdate; myUpdate.UpdateDate = ""; myUpdate.UpdateDes = ""; myUpdate.UpdateDes_Url = ""; myUpdate.UpdateVer ="未知"; myUpdate.UpdateType = ""; myUpdate.UpdateUrl = ""; myUpdate.FirstDownList = FirstDownList; myUpdate.sxSettingXML = SettingXML; if(RySoft.CompareVer(MySoftVer, MySoftRVer, SoftVer, ReVer)==1) { UpdateMarket = 1; myUpdate.UpdateDate = SoftDate; myUpdate.UpdateDes = SoftUpdateDes; myUpdate.UpdateVer = SoftVersion; myUpdate.UpdateType = "soft"; myUpdate.UpdateDes_Url = SoftUpdateDesUrl; if (FileVerUpdateUrl.Length > 0) { var list = FileVerUpdateUrl.Replace("\r", "").Split('\n'); for (int i = 0; i < list.Length; i++) { var item = list[i].Split('|'); if (item.Length < 2) { continue; } var ver = item[0]; var url = item[1]; RySoft.GetVerByVerStr(ver, out var _softver, out var _rever); if (RySoft.CompareVer(_softver, _rever, MySoftVer, MySoftRVer) <= 0) { FileUpdateUrl = url; break; } } } myUpdate.UpdateUrl = FileUpdateUrl; DownUrl = FileUpdateUrl; } else { if (MyDataVer < DataVer) //如果本地数据库版本小于远程服务器版本 { UpdateMarket = 2; myUpdate.UpdateDate = DataDate; myUpdate.UpdateDes = DataUpdateDes; myUpdate.UpdateVer = DataVer.ToString("0.000"); myUpdate.UpdateType = "data"; myUpdate.UpdateUrl = DbUpdateUrl; DownUrl = DbUpdateUrl; } } if (UpdateMarket > 0) { //如果没有指定更新用户,或者包含在指定更新用户里,则有更新 if (m_UpdateUserList.Length==0 || (m_UpdateUserList).IndexOf("|" + CurUserId + "|") >= 0) { if (m_UpdateUserList.Length > 0 && CurUserId.Length == 0) { OnNoUpdate_T(); } else { m_UpdateType = myUpdate; OnUpdateComplete_T(myUpdate); } } else { OnNoUpdate_T(); } } else { OnNoUpdate_T(); } } Thread threadDown; /// /// 开始下载 /// public void StartDownload() { isExit = false; if (threadDown != null) { threadDown.Abort(); } threadDown = new Thread(new ThreadStart(_Download)) { IsBackground = true }; threadDown.Start(); } /// /// 开始下载 /// public void StartDownload(string fileurl, string filename) { isExit = false; if (threadDown != null) { threadDown.Abort(); } threadDown = new Thread(delegate () { _Download(fileurl, filename); }); threadDown.IsBackground = true; threadDown.Start(); } /// /// 下载,不使用多线程 /// public bool DownloadInUI(string fileurl, string filename) { isExit = false; return _Download(fileurl, filename); } /// /// 结束下载 /// public void StopDownload() { if (threadDown != null) { threadDown.Abort(); } } private void _Download() { _Download(DownUrl, Application.StartupPath + "\\Update\\" + SaveFileName); } private bool _Download(string fileurl, string filename) { int retry = 0; retryits: try { System.Net.ServicePointManager.DefaultConnectionLimit = 512; HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(fileurl); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); long totalBytes = response.ContentLength; Stream st = response.GetResponseStream(); Stream so = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite); _DoEvent(fileurl, filename, totalBytes, 0, false, "开始下载...."); long totalDownloadedByte = 0; byte[] by = new byte[4096]; int osize = st.Read(by, 0, (int)by.Length); while (osize > 0) { if (isExit) { break; } totalDownloadedByte = osize + totalDownloadedByte; so.Write(by, 0, osize); osize = st.Read(by, 0, (int)by.Length); double p = totalDownloadedByte * 100.0 / totalBytes; if (p >= 100.0) p = 100.0; _DoEvent(fileurl, filename, totalBytes, p, false, String.Format("正在下载:{0}",RyFiles.GetFileSizeStr(totalDownloadedByte))); } so.Close(); st.Close(); _DoEvent(fileurl, filename, totalBytes, 100, true, "下载完成"); if (isExit) { return false; } return true; } catch (Exception ex) { retry++; if (retry < 5) { _DoEvent(fileurl, filename, 0, 0, false, String.Format("下载失败,第 {0} 次重试", retry)); // 休息 5 秒钟然后重试 Thread.Sleep(5000); goto retryits; } else { _DoEvent(fileurl, filename, 0, 0, false, "下载失败,原因是:" + ex.Message); return false; } } finally { Thread.Sleep(100); } } private void _DoEvent(string url, string filename, long filesize, double progress, bool iscompleted, string currentstatus) { if (ProgressChanged != null) { _LiveUpdateEventArgs.CurrentFileName = filename; _LiveUpdateEventArgs.CurrentFileSize = filesize; _LiveUpdateEventArgs.CurrentUrl = url; _LiveUpdateEventArgs.CurrProgress = progress; _LiveUpdateEventArgs.IsCompleted = iscompleted; _LiveUpdateEventArgs.CurrentStatus = currentstatus; this.ProgressChanged(this, _LiveUpdateEventArgs); Application.DoEvents(); } } } }