RaUI/Source/ryUpdate/myUpdate/clsLiveUpdate.cs

533 lines
20 KiB
C#
Raw Normal View History

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
{
/// <summary>
///
/// </summary>
public class ClsLiveUpdate
{
/// <summary>
/// 升级地址
/// </summary>
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 = "";//数据库更新地址
/// <summary>
///
/// </summary>
public string CurUserId = "";//当前用户id
/// <summary>
/// 隔多久后再次检查更新
/// </summary>
private int UpdateAfterTime =0;
/// <summary>
/// 本地保存的配置信息
/// </summary>
public string SettingPath = "";//设置地址
/// <summary>
/// 当前安装的软件版本
/// </summary>
public double MySoftVer = 0; //软件版本
/// <summary>
/// 当前安装的软件修正版本
/// </summary>
public double MySoftRVer = 0; //软件修正版本
/// <summary>
/// 当前安装的数据库版本
/// </summary>
public double MyDataVer = 0;//数据库版本
/// <summary>
///
/// </summary>
public string SaveFileName = "tmp.tmp";//下载的文件保存文件
/// <summary>
///
/// </summary>
public string DownUrl = "";//下载地址
/// <summary>
///
/// </summary>
public bool isExit = false;
private UpdateInfo m_UpdateType;
/// <summary>
/// 获取当前更新的类型
/// </summary>
public UpdateInfo UpdateType
{
get { return m_UpdateType; }
}
/// <summary>
/// 每隔n小时检测一次更新
/// </summary>
public int UpdateLoopHours =0;//每隔n小时检测一次
private delegate void dd1(bool message);
private Thread threadOne;
/// <summary>
/// 读取版本信息完成后激发
/// </summary>
[Description("读取版本信息完成后激发")]
public event EventHandler OnReadComplete;
/// <summary>
/// 没有版本更新时激发
/// </summary>
[Description("没有版本更新时激发")]
public event EventHandler OnNoUpdate;
/// <summary>
/// 发现新版本时激发
/// </summary>
[Description("发现新版本时激发")]
public event UpdateHandler OnUpdateComplete;
/// <summary>
/// 发生错误后激发
/// </summary>
[Description("发生错误后激发")]
public event ErrorHandler OnHappenError;
/// <summary>
/// 更新进度变化后激发
/// </summary>
[Description("更新进度变化后激发")]
public event LiveUpdate.LiveUpdateProgressChanged ProgressChanged;
private LiveUpdate.LiveUpdateEventArgs _LiveUpdateEventArgs = new LiveUpdate.LiveUpdateEventArgs();
/// <summary>
/// 开始检测新版本
/// </summary>
public void StartLiveUpdate() //开始升级
{
if (threadOne != null) { threadOne.Abort(); }
threadOne = new Thread(new ThreadStart(GetVerInfo));
threadOne.SetApartmentState(ApartmentState.STA);
threadOne.IsBackground = true;
threadOne.Start();
}
/// <summary>
///
/// </summary>
public Form ParentForm = null;
/// <summary>
/// 初始化升级函数
/// </summary>
/// <param name="ower">为null,则表示事件运行在多线程模式下,否则,事件是在窗体所在线程下</param>
public ClsLiveUpdate(Form ower)
{
ParentForm = ower;
MySoftVer = AssemblyVersion;
MySoftRVer = AssemblyReVersion;
SettingPath = Application.StartupPath + @"\cUpdate.dat";
MyDataVer = 0;
}
/// <summary>
///
/// </summary>
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);
}
}
}
/// <summary>
///
/// </summary>
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);
}
}
/// <summary>
/// 获取版本信息
/// </summary>
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("<root></root>");
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;
/// <summary>
/// 开始下载
/// </summary>
public void StartDownload()
{
isExit = false;
if (threadDown != null)
{
threadDown.Abort();
}
threadDown = new Thread(new ThreadStart(_Download))
{
IsBackground = true
};
threadDown.Start();
}
/// <summary>
/// 开始下载
/// </summary>
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();
}
/// <summary>
/// 下载,不使用多线程
/// </summary>
public bool DownloadInUI(string fileurl, string filename)
{
isExit = false;
return _Download(fileurl, filename);
}
/// <summary>
/// 结束下载
/// </summary>
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();
}
}
}
}