首页 > 名字大全 > 游戏名字 正文
(网页游戏自动升级)网页游戏排行榜2022前十名

时间:2023-05-02 11:34:18 阅读: 评论: 作者:佚名

一、引言

对于C/S架构来说,软件更新是一个很常用的功能,下面介绍一种非常实用的软件自动升级方案。

二、示意图

三、项目说明

3.1、项目创建

新建4个项目,如下所示:

3.2、项目关系

四、LinkTo.Toolkit

LinkTo.Toolkit主要是一些Utility及Helper类文件,实现转换扩展、文件读写、进程处理等功能。

/// <summary> /// 转换扩展类 /// </summary> public static class ConvertExtension { public static string ToString2(this object obj) { if (obj == null) return ; return obj.ToString(); } public static DateTime? ToDateTime(this string str) { if (str)) return null; if (str, out DateTime dateTime)) { return dateTime; } return null; } public static bool ToBoolean(this string str) { if (str)) return false; return () == bool.TrueS(); } public static bool IsNullOrEmpty(this string str) { return (str); } public static int ToInt(this string str) { if (str, out int intValue)) { return intValue; } return 0; } public static long ToLong(this string str) { if (str, out long longValue)) { return longValue; } return 0; } public static decimal ToDecimal(this string str) { if (str, out decimal decimalValue)) { return decimalValue; } return 0; } public static double ToDouble(this string str) { if (str, out double doubleValue)) { return doubleValue; } return 0; } public static float ToFloat(this string str) { if (str, out float floatValue)) { return floatValue; } return 0; } /// <summary> /// DataRow转换为实体类 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="dr"></param> /// <returns></returns> public static T ConvertToEntityByDataRow<T>(this DataRow dataRow) where T : new() { Type type = typeof(T); PropertyInfo[] properties = (); T t = new T(); if (dataRow == null) return t; foreach (PropertyInfo property in properties) { foreach (DataColumn column in da) { if , S)) { object value = dataRow[column]; if (value != null && value != DBNull.Value) { if ().Name != ) { if ) { (t, Enum.Parse, value.ToString()), null); } else { try { value = Convert.ChangeType(value, ) ?? )); (t, value, null); } catch { } } } else { (t, value, null); } } else { (t, null, null); } break; } } } return t; } /// <summary> /// 通用简单实体类型互转 /// </summary> public static T ConvertToEntity<T>(this object sourceEntity) where T : new() { T t = new T(); Type sourceType = (); if (typeof(DataRow))) { //DataRow类型 DataRow dataRow = sourceEntity as DataRow; t = da;T>(); } else { Type type = typeof(T); PropertyInfo[] properties = (); PropertyInfo[] sourceProperties = (); foreach (PropertyInfo property in properties) { foreach (var sourceProperty in sourceProperties) { if , S)) { object value = (sourceEntity, null); if (value != null && value != DBNull.Value) { if != ) { if ) { (t, Enum.Parse, value.ToString()), null); } else { try { value = Convert.ChangeType(value, ) ?? )); (t, value, null); } catch { } } } else { (t, value, null); } } else { (t, null, null); } break; } } } } return t; } /// <summary> /// 通用简单实体类型互转 /// </summary> public static List<T> ConvertToEntityList<T>(this object list) where T : new() { List<T> t = new List<T>(); if (list == null) return t; Type sourceObj = li(); if (typeof(DataTable))) { var dataTable = list as DataTable; t = da;DataRow>().Where(m => ! == Da || m.RowState == Da)).Select(m => m.ConvertToEntityByDataRow<T>()).ToList(); } else if (list is IEnumerable) { t = ((IList)list).Cast<object>().Select(m => m.ConvertToEntity<T>()).ToList(); } return t; } /// <summary> /// 转换为DataTable,如果是集合没有数据行的时候会抛异常。 /// </summary> /// <param name="list"></param> /// <returns></returns> public static DataTable ConvertToDataTable(this object list) { if (list == null) return null; DataTable dataTable = new DataTable(); if (list is IEnumerable) { var li = (IList)list; //li[0]代表的是一个对象,list没有行时,会抛异常。 PropertyInfo[] properties = li[0].GetType().GetProperties(); da(m => !m.Pro || !m.Pro).Select(m => new DataColumn, Nullable.GetUnderlyingType) ?? m.PropertyType)).ToArray()); foreach (var item in li) { DataRow dataRow = da(); foreach (PropertyInfo property in (m => m.Pro("Item") == null)) //过滤含有索引器的属性 { object value = (item, null); dataRow[] = value ?? DBNull.Value; } da(dataRow); } } else { PropertyInfo[] properties = li().GetProperties(); properties = (m => m.Pro("Item") == null).ToArray(); //过滤含有索引器的属性 da(m => new DataColumn, Nullable.GetUnderlyingType) ?? m.PropertyType)).ToArray()); DataRow dataRow = da(); foreach (PropertyInfo property in properties) { object value = (list, null); dataRow[] = value ?? DBNull.Value; } da(dataRow); } return dataTable; } /// <summary> /// 实体类公共属性值复制 /// </summary> /// <param name="entity"></param> /// <param name="target"></param> public static void CopyTo(this object entity, object target) { if (target == null) return; if () != ()) return; PropertyInfo[] properties = ().GetProperties(); foreach (PropertyInfo property in properties) { if .GetProperty("Item") != null) continue; object value = (entity, null); if (value != null) { if (value is ICloneable) { (target, (value as ICloneable).Clone(), null); } else { (target, value.Copy(), null); } } else { (target, null, null); } } } public static object Copy(this object obj) { if (obj == null) return null; object targetDeepCopyObj; Type targetType = obj.GetType(); if == true) { targetDeepCopyObj = obj; } else { targetDeepCopyObj = Ac(targetType); //创建引用对象 MemberInfo[] memberCollection = obj.GetType().GetMembers(); foreach (MemberInfo member in memberCollection) { if ().GetProperty("Item") != null) continue; if == MemberTy) { FieldInfo field = (FieldInfo)member; object fieldValue = (obj); if (fieldValue is ICloneable) { (targetDeepCopyObj, (fieldValue as ICloneable).Clone()); } else { (targetDeepCopyObj, ()); } } else if == MemberTy) { PropertyInfo property = (PropertyInfo)member; MethodInfo method = (false); if (method != null) { object propertyValue = (obj, null); if (propertyValue is ICloneable) { (targetDeepCopyObj, (propertyValue as ICloneable).Clone(), null); } else { (targetDeepCopyObj, (), null); } } } } } return targetDeepCopyObj; } }

public class FileHelper { private readonly string strUpdateFilesPath; public FileHelper(string strDirector) { strUpdateFilesPath = strDirector; } //保存所有的文件信息 private List<FileInfo> listFiles = new List<FileInfo>(); public List<FileInfo> GetAllFilesInDirectory(string strDirector) { DirectoryInfo directory = new DirectoryInfo(strDirector); DirectoryInfo[] directoryArray = direc(); FileInfo[] fileInfoArray = direc(); if > 0) li(fileInfoArray); foreach (DirectoryInfo item in directoryArray) { DirectoryInfo directoryA = new DirectoryInfo); DirectoryInfo[] directoryArrayA = direc(); GetAllFilesInDirectory); } return listFiles; } public string[] GetUpdateList(List<FileInfo> listFileInfo) { var fileArrary = li;FileInfo>().Select(s => s.FullName.Replace(strUpdateFilesPath, "")).ToArray(); return fileArrary; } /// <summary> /// 删除文件夹下的所有文件但不删除目录 /// </summary> /// <param name="dirRoot"></param> public static void DeleteDirAllFile(string dirRoot) { DirectoryInfo directoryInfo = new DirectoryInfo(dirRoot)); FileInfo[] files = direc("*.*", Searc); foreach (FileInfo item in files) { File.Delete); } } }

public static class FileUtility { #region 读取文件 /// <summary> /// 读取文件 /// </summary> /// <param name="filePath">文件路径</param> /// <returns></returns> public static string ReadFile(string filePath) { string result = ; if (filePath) == false) { return result; } try { using (var streamReader = new StreamReader(filePath, Encoding.UTF8)) { result = (); } } catch (Exception) { result = ; } return result; } #endregion 读文件 #region 写入文件 /// <summary> /// 写入文件 /// </summary> /// <param name="filePath">文件路径</param> /// <param name="strValue">写入内容</param> /// <returns></returns> public static bool WriteFile(string filePath, string strValue) { try { if (filePath) == false) { using (FileStream fileStream = File.Create(filePath)) { } } using (var streamWriter = new StreamWriter(filePath, true, Encoding.UTF8)) { (strValue); } return true; } catch (Exception) { return false; } } #endregion #region 删除文件 /// <summary> /// 删除文件 /// </summary> /// <param name="filePath">文件路径</param> /// <returns></returns> public static bool DeleteFile(string filePath) { try { File.Delete(filePath); return true; } catch (Exception) { return false; } } #endregion 删除文件 #region 为文件添加用户组的完全控制权限 /// <summary> /// 为文件添加用户组的完全控制权限 /// </summary> /// <param name="userGroup">用户组</param> /// <param name="filePath">文件路径</param> /// <returns></returns> public static bool AddSecurityControll2File(string userGroup, string filePath) { try { //获取文件信息 FileInfo fileInfo = new FileInfo(filePath); //获得该文件的访问权限 FileSecurity fileSecurity = (); //添加用户组的访问权限规则--完全控制权限 (new FileSystemAccessRule(userGroup, FileSy, Acce)); //设置访问权限 (fileSecurity); //返回结果 return true; } catch (Exception) { //返回结果 return false; } } #endregion #region 为文件夹添加用户组的完全控制权限 /// <summary> /// 为文件夹添加用户组的完全控制权限 /// </summary> /// <param name="userGroup">用户组</param> /// <param name="dirPath">文件夹路径</param> /// <returns></returns> public static bool AddSecurityControll2Folder(string userGroup,string dirPath) { try { //获取文件夹信息 DirectoryInfo dir = new DirectoryInfo(dirPath); //获得该文件夹的所有访问权限 DirectorySecurity dirSecurity = dir.GetAccessControl); //设定文件ACL继承 InheritanceFlags inherits = In | In; //添加用户组的访问权限规则--完全控制权限 FileSystemAccessRule usersFileSystemAccessRule = new FileSystemAccessRule(userGroup, FileSy, inherits, Pro, Acce); dirSecuri, usersFileSystemAccessRule, out bool isModified); //设置访问权限 dir.SetAccessControl(dirSecurity); //返回结果 return true; } catch (Exception) { //返回结果 return false; } } #endregion }

public static class ProcessUtility { #region 关闭进程 /// <summary> /// 关闭进程 /// </summary> /// <param name="processName">进程名</param> public static void KillProcess(string processName) { Process[] myproc = Proce(); foreach (Process item in myproc) { if == processName) { i(); } } } #endregion }

/// <summary> /// Xml序列化与反序列化 /// </summary> public static class XmlUtility { #region 序列化 /// <summary> /// 序列化 /// </summary> /// <param name="type">类型</param> /// <param name="obj">对象</param> /// <returns></returns> public static string Serializer(Type type, object obj) { MemoryStream Stream = new MemoryStream(); XmlSerializer xml = new XmlSerializer(type); try { //序列化对象 xml.Serialize(Stream, obj); } catch (InvalidOperationException) { throw; } S = 0; StreamReader sr = new StreamReader(Stream); string str = (); (); S(); return str; } #endregion 序列化 #region 反序列化 /// <summary> /// 反序列化 /// </summary> /// <param name="type">类型</param> /// <param name="xml">XML字符串</param> /// <returns></returns> public static object Deserialize(Type type, string xml) { try { using (StringReader sr = new StringReader(xml)) { XmlSerializer xmldes = new XmlSerializer(type); return xmldes.Deserialize(sr); } } catch (Exception ex) { return ex.Message; } } /// <summary> /// 反序列化 /// </summary> /// <param name="type"></param> /// <param name="xml"></param> /// <returns></returns> public static object Deserialize(Type type, Stream stream) { XmlSerializer xmldes = new XmlSerializer(type); return xmldes.Deserialize(stream); } #endregion 反序列化 }

五、AutoUpdaterTest

5.1、实体类

作用:本地配置Au文件的序列化及反序列化实体对象。

public class AutoUpdateConfig { /// <summary> /// 自动升级模式:当前仅支持HTTP /// </summary> public string AutoUpdateMode { get; set; } /// <summary> /// HTTP自动升级模式时的URL地址 /// </summary> public string AutoUpdateHttpUrl { get; set; } }

5.2、通用类

作用:应用程序全局静态常量。全局参数都在此设置,方便统一管理。注:客户端是否检测更新,也是在此设置默认值。

/// <summary> /// 应用程序全局静态常量 /// </summary> public static class GlobalParam { #region 自动更新参数 /// <summary> /// 是否检查自动更新:默认是true /// </summary> public static string CheckAutoUpdate = "true"; /// <summary> /// 本地自动更新配置XML文件名 /// </summary> public const string AutoUpdateConfig_XmlFileName = "Au"; /// <summary> /// 本地自动更新下载临时存放目录 /// </summary> public const string TempDir = "Temp"; /// <summary> /// 远端自动更新信息XML文件名 /// </summary> public const string AutoUpdateInfo_XmlFileName = "Au;; /// <summary> /// 远端自动更新文件存放目录 /// </summary> public const string RemoteDir = "AutoUpdateFiles"; /// <summary> /// 主线程名 /// </summary> public const string MainProcess = "AutoUpdaterTest"; #endregion }

作用:应用程序上下文。

/// <summary> /// 应用程序上下文 /// </summary> public class AppContext { /// <summary> /// 客户端配置文件 /// </summary> public static AutoUpdateConfig AutoUpdateConfigData { get; set; } }

作用:应用程序配置。

public class AppConfig { private static readonly object _lock = new object(); private static AppConfig _instance = null; #region 自动更新配置 /// <summary> /// 自动更新配置数据 /// </summary> public AutoUpdateConfig AutoUpdateConfigData { get; set; } private AppConfig() { AutoUpdateConfigData = new AutoUpdateConfig(); } public static AppConfig Instance { get { if (_instance == null) { lock (_lock) { if (_instance == null) { _instance = new AppConfig(); } } } return _instance; } } /// <summary> /// 本地自动更新下载临时文件夹路径 /// </summary> public string TempPath { get { return ("{0}\\{1}", A, GlobalParam.TempDir); } } /// <summary> /// 初始化系统配置信息 /// </summary> public void InitialSystemConfig() { Au = AppContext.Au; Au = AppContext.Au; } #endregion }

5.3、工具类

作用:配置文件的读写。

public class AutoUpdateHelper { private readonly string AutoUpdateMode = ; public AutoUpdateHelper(string autoUpdateMode) { AutoUpdateMode = autoUpdateMode; } /// <summary> /// 加载本地自动更新配置文件 /// </summary> /// <returns></returns> public static AutoUpdateConfig Load() { string filePath = , fileContent = ; filePath = Pa(A, GlobalParam.AutoUpdateConfig_XmlFileName); AutoUpdateConfig config = new AutoUpdateConfig(); fileContent = FileU(filePath); object obj = XmlU(typeof(AutoUpdateConfig), fileContent); config = obj as AutoUpdateConfig; return config; } /// <summary> /// 获取远端自动更新信息的版本号 /// </summary> /// <returns></returns> public string GetRemoteAutoUpdateInfoVersion() { XDocument doc = new XDocument(); doc = XDocument.Parse(GetRemoteAutoUpdateInfoXml()); return doc.Element("AutoUpdateInfo").Element("NewVersion").Value; } /// <summary> /// 获取远端自动更新信息的XML文件内容 /// </summary> /// <returns></returns> public string GetRemoteAutoUpdateInfoXml() { string remoteXmlAddress = AppConfig.Instance.Au + "/" + GlobalParam.AutoUpdateInfo_XmlFileName; string receiveXmlPath = Pa, GlobalParam.AutoUpdateInfo_XmlFileName); string xmlString = ; if ) == false) { Direc); } if () == "HTTP") { WebClient client = new WebClient(); client.DownloadFile(remoteXmlAddress, receiveXmlPath); } if (receiveXmlPath)) { xmlString = FileU(receiveXmlPath); return xmlString; } return ; } /// <summary> /// 写入本地自动更新配置的XML文件内容 /// </summary> /// <returns></returns> public string WriteLocalAutoUpdateInfoXml() { string xmlPath = , xmlValue = ; xmlPath = Pa, GlobalParam.AutoUpdateConfig_XmlFileName); xmlValue = XmlU(typeof(AutoUpdateConfig), A); if (xmlPath)) { File.Delete(xmlPath); } bool blSuccess = FileU(xmlPath, xmlValue); return blSuccess == true ? xmlPath : ""; } }

5.4、本地配置文件

作用:配置自动更新模式及相关。

注1:复制到输出目录选择始终复制。

注2:主程序运行时,先读取此配置更新文件,然后给AppContext上下文赋值,接着给AppConfig配置赋值。

<?xml version="1.0" encoding="utf-8" ?> <AutoUpdateConfig> <!--自动升级模式:当前仅支持HTTP--> <AutoUpdateMode>HTTP</AutoUpdateMode> <!--HTTP自动升级模式时的URL地址--> <AutoUpdateHttpUrl>;/AutoUpdateHttpUrl> </AutoUpdateConfig>

5.5、主程序

新建一个Windows 窗体MainForm,此处理仅需要一个空白窗体即可,作测试用。

public partial class MainForm : Form { private static MainForm _Instance; /// <summary> /// MainForm主窗体实例 /// </summary> public static MainForm Instance { get { if (_Instance == null) { _Instance = new MainForm(); } return _Instance; } } public MainForm() { InitializeComponent(); } }

5.6、应用程序主入口

作用:检测应用程序是否需要自动更新,如里需要则检测远程服务端的版本号。假如远程服务端有新版本,则调用自动更新器AutoUpdater并向其传递4个参数。

internal static class Program { /// <summary> /// 应用程序的主入口点 /// </summary> [STAThread] private static void Main(string[] args) { //尝试设置访问权限 FileU("Users", A); //未捕获的异常处理 A += Application_ThreadException; A); A += CurrentDomain_UnhandledException; //是否检查自动更新赋值 if > 0) { GlobalParam.CheckAutoUpdate = args[0]; } //加载自动更新配置文件,给上下文AppServiceConfig对象赋值。 var config = Au(); A = config; //窗体互斥体 var instance = new Mutex(true, GlobalParam.MainProcess, out bool isNewInstance); if (isNewInstance == true) { if ()) { if (CheckUpdater()) Proce); } A(); A(false); A); in(); } else { Me("已经启动了一个程序,请先退出。", "提示", Me, Me); A(); } } /// <summary> /// 自动更新检测 /// </summary> /// <returns></returns> private static bool CheckUpdater() { if () == false) return false; #region 检查版本更新 Stopwatch stopwatch = new Stopwatch(); (); bool blFinish = false; A(); var helper = new AutoUpdateHelper(AppConfig.Instance.Au); string fileVersion = FileVer).FileVersion; long localVersion = 0; long remoteVersion = 0; try { localVersion = (".", "").ToLong(); remoteVersion = ().Replace(".", "").ToLong(); if ((localVersion > 0) && (localVersion < remoteVersion)) { blFinish = true; string autoUpdateConfigXmlPath = (); string autoUpdateInfoXmlPath = Pa, GlobalParam.AutoUpdateInfo_XmlFileName); string argument1 = autoUpdateConfigXmlPath; string argument2 = autoUpdateInfoXmlPath; string argument3 = GlobalParam.MainProcess; string argument4 = GlobalParam.RemoteDir; string arguments = argument1 + " " + argument2 + " " + argument3 + " " + argument4; Proce("Au;, arguments); A(); } } catch (TimeoutException) { blFinish = false; } catch (WebException) { blFinish = false; } catch (Exception) { blFinish = false; } return blFinish; #endregion } /// <summary> /// UI线程未捕获异常处理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) { string strError = "", strLog = "", strDateInfo = Da() + " 出现应用程序未处理的异常:\r\n"; var error = e.Exception; if (error != null) { strError = strDateInfo + $"异常类型:{error.GetType().Name}\r\n异常消息:{error.Message}"; strLog = strDateInfo + $"异常类型:{error.GetType().Name}\r\n异常消息:{error.Message}\r\n堆栈信息:{error.StackTrace}\r\n来源信息:{error.Source}\r\n"; } else { strError = $"Application ThreadException:{e}"; } WriteLog(strLog); Me(strError, "系统错误", Me, Me); } /// <summary> /// 非UI线程未捕获异常处理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { string strError = "", strLog = "", strDateInfo = Da() + " 出现应用程序未处理的异常:\r\n"; if is Exception error) { strError = strDateInfo + $"异常消息:{error.Message}"; strLog = strDateInfo + $"异常消息:{error.Message}\r\n堆栈信息:{error.StackTrace}"; } else { strError = $"Application UnhandledError:{e}"; } WriteLog(strLog); Me(strError, "系统错误", Me, Me); } /// <summary> /// 写入日志 /// </summary> /// <param name="strLog"></param> private static void WriteLog(string strLog) { string dirPath = @"Log\MainProcess", fileName = Da("yyyy-MM-dd") + ".txt"; string strLine = "----------------------------------------------------------------------------------------------------"; FileU(Pa(dirPath, fileName), strLog); FileU(Pa(dirPath,fileName), strLine); } }

六、AutoUpdater

6.1、实体类

作用:配置自动更新模式及相关。

/// <summary> /// 自动更新配置信息 /// </summary> public class AutoUpdateConfig { /// <summary> /// 自动升级模式:当前仅支持HTTP /// </summary> public string AutoUpdateMode { get; set; } /// <summary> /// HTTP自动升级模式时的URL地址 /// </summary> public string AutoUpdateHttpUrl { get; set; } }

作用:自动更新内容信息。

/// <summary> /// 自动更新内容信息 /// </summary> [Serializable] public class AutoUpdateInfo { /// <summary> /// 新版本号 /// </summary> public string NewVersion { get; set; } /// <summary> /// 更新日期 /// </summary> public string UpdateTime { get; set; } /// <summary> /// 更新内容说明 /// </summary> public string UpdateContent { get; set; } /// <summary> /// 更新文件列表 /// </summary> public List<string> FileList { get; set; } }

6.2、通用类

作用:应用程序全局静态常量。全局参数都在此设置,方便统一管理。

/// <summary> /// 应用程序全局静态常量 /// </summary> public static class GlobalParam { /// <summary> /// 调用程序主线程名称 /// </summary> public static string MainProcess = ; /// <summary> /// 远程更新程序所在文件夹的名称 /// </summary> public static string RemoteDir = ; }

6.3、Window 窗体

新建一个Windows 窗体HttpStartUp。

public partial class HttpStartUp : Form { private bool _blSuccess = false; private string _autoUpdateHttpUrl = null; private AutoUpdateInfo _autoUpdateInfo = null; public HttpStartUp(string autoUpdateHttpUrl, AutoUpdateInfo autoUpdateInfo) { InitializeComponent(); _autoUpdateHttpUrl = autoUpdateHttpUrl; _autoUpdateInfo = autoUpdateInfo; _blSuccess = false; } /// <summary> /// 窗体加载事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Main_Load(object sender, EventArgs e) { Text = GlobalParam.MainProcess + "-更新程序"; lblU = _au; lblNewVer = _au; = _au; } /// <summary> /// 立即更新 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnRun_Click(object sender, EventArgs e) { Proce); b = false; b = false; Thread thread = new Thread(() => { try { var downFileList = _au(s => s.IndexOf("\\")); foreach (var fileName in downFileList) { string fileUrl = , fileVaildPath = ; if ("\\")) { fileVaildPath = ("\\")); } else { fileVaildPath = fileName; } fileUrl = _au(new char[] { '/' }) + @"/" + GlobalParam.RemoteDir + @"/" + ("\\", "/"); //替换文件目录中的路径为网络路径 DownloadFileDetail(fileUrl, fileName); } _blSuccess = true; } catch (Exception ex) { BeginInvoke(new MethodInvoker(() => { throw ex; })); } finally { BeginInvoke(new MethodInvoker(delegate () { b = true; b = true; })); } if (_blSuccess) { Proce + ".exe"); BeginInvoke(new MethodInvoker(delegate () { Close(); A(); })); } }) { IsBackground = true }; (); } private void DownloadFileDetail(string httpUrl, string filename) { string fileName = A + "\\" + filename; string dirPath = GetDirPath(fileName); if (!Direc(dirPath)) { Direc(dirPath); } HttpWebRequest request = (HttpWebReque(httpUrl); HttpWebResponse response = (HttpWebResponse(); Stream httpStream = re(); long totalBytes = re; if (progressBar != null) { BeginInvoke(new MethodInvoker(delegate () { lblDownIn = "开始下载..."; = (int)totalBytes; = 0; })); } FileStream outputStream = new FileStream(fileName, FileMode.Create); int bufferSize = 2048; int readCount; byte[] buffer = new byte[bufferSize]; readCount = (buffer, 0, bufferSize); int allByte = (int)re; int startByte = 0; BeginInvoke(new MethodInvoker(delegate () { = allByte; = 0; })); while (readCount > 0) { ou(buffer, 0, readCount); readCount = (buffer, 0, bufferSize); startByte += readCount; BeginInvoke(new MethodInvoker(delegate () { lblDownIn = "已下载:" + startByte / 1024 + "KB/" + "总长度:"+ allByte / 1024 + "KB" + " " + " 文件名:" + filename; = startByte; })); A(); T(5); } BeginInvoke(new MethodInvoker(delegate () { lblDownIn = "下载完成。"; })); (); ou(); re(); } public static string GetDirPath(string filePath) { if ("\\") > 0) { return (0, ("\\")); } return filePath; } /// <summary> /// 暂不更新 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnLeave_Click(object sender, EventArgs e) { if (Me("确定要放弃此次更新吗?", "提示", Me, Me) == DialogRe) { Proce + ".exe", "false"); Close(); A(); } } }

6.4、应用程序主入口

internal static class Program { /// <summary> /// 应用程序的主入口点 /// </summary> [STAThread] private static void Main(string[] args) { A); A += new Sy(Application_ThreadException); A += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); A(); A(false); #region 测试 //string strArgs = @"E:\LinkTo.AutoUpdater\AutoUpdaterTest\bin\Debug\Temp\Au"+" "+@"E:\LinkTo.AutoUpdater\AutoUpdaterTest\bin\Debug\Temp\Au;+" "+"AutoUpdaterTest"+" "+"AutoUpdateFiles"; //args = (' '); #endregion if > 0) { string autoUpdateConfigXmlPath = args[0].ToString(); string autoUpdateInfoXmlPath = args[1].ToString(); GlobalParam.MainProcess = args[2].ToString(); GlobalParam.RemoteDir = args[3].ToString(); var autoUpdateConfigXml = FileU(autoUpdateConfigXmlPath); var autoUpdateInfoXml = FileU(autoUpdateInfoXmlPath); AutoUpdateConfig config = XmlU(typeof(AutoUpdateConfig), autoUpdateConfigXml) as AutoUpdateConfig; AutoUpdateInfo info = XmlU(typeof(AutoUpdateInfo), autoUpdateInfoXml) as AutoUpdateInfo; if () == "HTTP") { A(new HttpStartU, info)); } } else { A(); } } /// <summary> /// UI线程未捕获异常处理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public static void Application_ThreadException(object sender, Sy e) { string strError = "", strLog = "", strDateInfo = Da() + " 出现应用程序未处理的异常:\r\n"; var error = e.Exception; if (error != null) { strError = strDateInfo + $"异常类型:{error.GetType().Name}\r\n异常消息:{error.Message}"; strLog = strDateInfo + $"异常类型:{error.GetType().Name}\r\n异常消息:{error.Message}\r\n堆栈信息:{error.StackTrace}\r\n来源信息:{error.Source}\r\n"; } else { strError = $"Application ThreadException:{e}"; } WriteLog(strLog); Me(strError, "系统错误", Me, Me); } /// <summary> /// 非UI线程未捕获异常处理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { string strError = "", strLog = "", strDateInfo = Da() + " 出现应用程序未处理的异常:\r\n"; if is Exception error) { strError = strDateInfo + $"异常消息:{error.Message}"; strLog = strDateInfo + $"异常消息:{error.Message}\r\n堆栈信息:{error.StackTrace}"; } else { strError = $"Application UnhandledError:{e}"; } WriteLog(strLog); Me(strError, "系统错误", Me, Me); } /// <summary> /// 写入日志 /// </summary> /// <param name="strLog"></param> private static void WriteLog(string strLog) { string dirPath = @"Log\AutoUpdater", fileName = Da("yyyy-MM-dd") + ".txt"; string strLine = "----------------------------------------------------------------------------------------------------"; FileU(Pa(dirPath, fileName), strLog); FileU(Pa(dirPath, fileName), strLine); } }

七、AutoUpdateXmlBuilder

7.1、实体类

作用:自动更新内容信息。

/// <summary> /// 自动更新内容信息 /// </summary> [Serializable] public class AutoUpdateInfo { /// <summary> /// 新版本号 /// </summary> public string NewVersion { get; set; } /// <summary> /// 更新日期 /// </summary> public string UpdateTime { get; set; } /// <summary> /// 更新内容说明 /// </summary> public string UpdateContent { get; set; } /// <summary> /// 更新文件列表 /// </summary> public List<string> FileList { get; set; } }

7.2、通用类

作用:应用程序全局静态常量。全局参数都在此设置,方便统一管理。

/// <summary> /// 应用程序全局静态常量 /// </summary> public static class GlobalParam { /// <summary> /// 远端自动更新信息XML文件名 /// </summary> public const string AutoUpdateInfo_XmlFileName = "Au;; /// <summary> /// 远端自动更新目录 /// </summary> public const string AutoUpdateDir = "AutoUpdateDir"; /// <summary> /// 远端自动更新文件存放目录 /// </summary> public const string RemoteDir = "AutoUpdateFiles"; /// <summary> /// 主线程名 /// </summary> public const string MainProcess = "AutoUpdaterTest"; }

7.3、Window 窗体

1)新建一个Windows 窗体Main。

public partial class Main : Form { //自动更新目录路径 private static readonly string AutoUpdateDirPath = A + @"\" + GlobalParam.AutoUpdateDir; //自动更新信息XML文件路径 private static readonly string AutoUpdateInfoXmlPath = Pa(AutoUpdateDirPath, GlobalParam.AutoUpdateInfo_XmlFileName); //自动更新文件目录路径 private static readonly string RemoteDirPath = A + @"\" + GlobalParam.AutoUpdateDir + @"\" + GlobalParam.RemoteDir; public Main() { InitializeComponent(); } /// <summary> /// 窗体加载 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Main_Load(object sender, EventArgs e) { if (!Direc(RemoteDirPath)) { Direc(RemoteDirPath); } LoadBaseInfo(); LoadDirectoryFileList(); } /// <summary> /// 刷新 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnRefresh_Click(object sender, EventArgs e) { LoadBaseInfo(); LoadDirectoryFileList(); } /// <summary> /// 初始化 /// </summary> private void LoadBaseInfo() { dtU = Da("yyyy-MM-dd"); txtNewVer = GetMainProcessFileVersion(); CreateHeaderAndFillListView(); } /// <summary> /// 获取主程序文件版本 /// </summary> /// <returns></returns> private string GetMainProcessFileVersion() { string fileVersion = ""; if (RemoteDirPath + "\\" + GlobalParam.MainProcess + ".exe")) //如果更新中有主程序文件 { FileVersionInfo info = FileVer(RemoteDirPath + "\\" + GlobalParam.MainProcess + ".exe"); fileVersion = in; } return fileVersion; } /// <summary> /// 添加ListView列名 /// </summary> private void CreateHeaderAndFillListView() { l(); int lvWithd = l; ColumnHeader columnHeader; //First Header columnHeader = new ColumnHeader { Text = "#", Width = 38 }; l(columnHeader); //Second Header columnHeader = new ColumnHeader { Text = "文件名", Width = (lvWithd - 38) / 2 }; l(columnHeader); //Third Header columnHeader = new ColumnHeader { Text = "更新路径", Width = (lvWithd - 38) / 2 }; l(columnHeader); } /// <summary> /// 加载目录文件列表 /// </summary> private void LoadDirectoryFileList() { if (!Direc(RemoteDirPath)) { Direc(RemoteDirPath); } FileHelper fileHelper = new FileHelper(RemoteDirPath); var fileArrary = (RemoteDirPath)).ToList(); var lastFile = (s => s == GlobalParam.MainProcess + ".exe"); //exe作为最后的文件更新,防止更新过程中出现网络错误,导致文件未全部更新。 if (lastFile != null) { (lastFile); (lastFile); } PopulateListViewWithArray()); } /// <summary> /// 使用路径字符数组填充列表 /// </summary> /// <param name="strArray"></param> private void PopulateListViewWithArray(string[] strArray) { l(); if (strArray != null) { //只过滤根目录下的特殊文件 strArray = (s => !new string[] { GlobalParam.AutoUpdateInfo_XmlFileName }.Contain('\\') + 1))).ToArray(); for (int i = 0; i < ; i++) { ListViewItem lvi = new ListViewItem { Text = (i + 1).ToString() }; int intStart = strArray[i].LastIndexOf('\\') + 1; lvi.SubI(strArray[i].Substring(intStart, strArray[i].Length - intStart)); lvi.SubI(strArray[i]); lstFileList.I(lvi); } } } /// <summary> /// 生成更新XML文件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnBuild_Click(object sender, EventArgs e) { if (txtNewVer)) { Me("更新版本号不能为空。", "提示", Me, Me); (); return; } if )) { Me("主进程名不能为空。", "提示", Me, Me); (); return; } AutoUpdateInfo info = new AutoUpdateInfo() { NewVersion = txtNewVer.Trim(), UpdateTime = d("yyyy-MM-dd"), UpdateContent = , FileList = l;ListViewItem>().Select(s => s.SubItems[2].Text).ToList() }; string xmlValue = XmlU(typeof(AutoUpdateInfo), info); using (StreamWriter sw = new StreamWriter(AutoUpdateInfoXmlPath)) { (xmlValue); (); (); } Me("生成成功。", "提示", Me, Me); } /// <summary> /// 打开本地目录 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnOpen_Click(object sender, EventArgs e) { ProcessStartInfo psi = new ProcessStartInfo("Ex;) { Arguments = AutoUpdateDirPath }; Proce(psi); } }

2)在bin\Debug\下新建一个AutoUpdateDir文件夹,然后再在AutoUpdateDir下新建一个AutoUpdateFiles文件夹。

3)在AutoUpdaterTest中,将程序集版本及文件版本都改成1.0.0.1并重新生成,接着将Au拷贝到AutoUpdateFiles下,最后将程序集版本及文件版本都改回1.0.0.0。

4)此时运行AutoUpdateXmlBuilder,点击生成更新XML文件即打包成功。程序会自动在AutoUpdateDir下生成打包信息文件Au。

7.4、应用程序主入口

internal static class Program { /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] private static void Main() { A); A += new Sy(Application_ThreadException); A += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); A(); A(false); A(new Main()); } /// <summary> /// UI线程未捕获异常处理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public static void Application_ThreadException(object sender, Sy e) { string strError = "", strLog = "", strDateInfo = Da() + " 出现应用程序未处理的异常:\r\n"; var error = e.Exception; if (error != null) { strError = strDateInfo + $"异常类型:{error.GetType().Name}\r\n异常消息:{error.Message}"; strLog = strDateInfo + $"异常类型:{error.GetType().Name}\r\n异常消息:{error.Message}\r\n堆栈信息:{error.StackTrace}\r\n来源信息:{error.Source}\r\n"; } else { strError = $"Application ThreadException:{e}"; } WriteLog(strLog); Me(strError, "系统错误", Me, Me); } /// <summary> /// 非UI线程未捕获异常处理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { string strError = "", strLog = "", strDateInfo = Da() + " 出现应用程序未处理的异常:\r\n"; if is Exception error) { strError = strDateInfo + $"异常消息:{error.Message}"; strLog = strDateInfo + $"异常消息:{error.Message}\r\n堆栈信息:{error.StackTrace}"; } else { strError = $"Application UnhandledError:{e}"; } WriteLog(strLog); Me(strError, "系统错误", Me, Me); } /// <summary> /// 写入日志 /// </summary> /// <param name="strLog"></param> private static void WriteLog(string strLog) { string dirPath = @"Log\XmlBuilder", fileName = Da("yyyy-MM-dd") + ".txt"; string strLine = "----------------------------------------------------------------------------------------------------"; FileU(Pa(dirPath, fileName), strLog); FileU(Pa(dirPath, fileName), strLine); } }

八、远程服务端配置

注:此处为本机测试。

1)在某个盘符如E盘下新建一个AutoUpdate文件夹,将AutoUpdateXmlBuilder打包文件夹AutoUpdateDir拷贝到AutoUpdate文件夹下。

2)在IIS中新建一个网站,对应的虚拟目录为E:\AutoyuaUpdate,同时将端口设置为6600。

3)运行AutoUpdaterTest,如出现自动更新器即代表成功。

源码下载:

  • 相关阅读
  • 评论列表

发表评论: