C#程序设计:为应用添加自动更新和运行异常信息捕获
小标 2018-06-07 来源 : 阅读 706 评论 0

摘要:本文主要向大家介绍了C#程序设计的为应用添加自动更新和运行异常信息捕获,希望对大家学习C#程序设计有所帮助。

本文主要向大家介绍了C#程序设计的为应用添加自动更新和运行异常信息捕获,希望对大家学习C#程序设计有所帮助。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace FileExtractionTool
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            ApplicationException.Run(call);     // 调用异常信息捕获类,进行异常信息的捕获
        }
 
        // 应用程序,入口逻辑
        public static void call()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            if (Update.Updated()) Application.Run(new Form1());
        }
    }
 
}

    

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace FileExtractionTool
{
 
    class Update
    {
        //public static string ToolsName = "easyIcon";                          // 工具名称
        static string ToolsName = "FileExtractionTool(文件提取检测工具)";     // 工具名称
        static long curVersion = 20160810;                                      // 记录当前软件版本信息
 
 
        /// <summary>
        /// 检查工具是否已是最新版本, 不是则自动更新
        /// </summary>
        public static bool Updated()
        {
            try
            {
                // 获取版本配置信息 示例:scimence( Name1(6JSO-F2CM-4LQJ-JN8P) )scimence
                string VersionInfo = WebSettings.getWebData("https://git.oschina.net/scimence/fileExtractionTool/raw/master/files/versionInfo.txt");
                if (VersionInfo.Equals("")) return true;
 
                // 获取版本更新信息
                long lastVersion = long.Parse(WebSettings.getNodeData(VersionInfo, "version", true));
                string url = WebSettings.getNodeData(VersionInfo, "url", true);
 
                // 检测到新的版本
                if (lastVersion > curVersion)
                {
                    bool ok = (MessageBox.Show("检测到新的版本,现在更新?", "版本更新", MessageBoxButtons.OKCancel) == DialogResult.OK);
                    if (ok)
                    {
                        CheckUpdateEXE();
 
                        // 获取更新插件名
                        string update_EXE = curDir() + "UpdateFiles.exe";
                        if (System.IO.File.Exists(update_EXE))
                        {
                            // 获取url中对应的文件名
                            string fileName = curDir() + System.IO.Path.GetFileName(url);
 
                            // 生成更新时的显示信息
                            String info = "当前版本:" + curVersion + "\r\n" + "最新版本:" + lastVersion + "\r\n";
 
                            // 调用更新插件执行软件更新逻辑
                            String arg = "\"" + url + "\"" + " " + "\"" + fileName + "\"" + " " + "true" + " " + "\"" + info + "\"";
                            System.Diagnostics.Process.Start(update_EXE, arg);
 
                            return false;
                        }
                        else MessageBox.Show("未找到更新插件:\r\n" + update_EXE);
                    }
                }
 
                return true;
            }
            catch (Exception ex) { return true; }  // 未获取到版本信息
        }
 
        // 检测更新插件UpdateFiles.exe是否存在,更新替换文件逻辑
        private static void CheckUpdateEXE()
        {
            string info = "更新UpdateFiles.exe\r\n";
 
            // 若文件不存在则自动创建
            string file1 = curDir() + "UpdateFiles.exe";
 
            string key = @"Scimence\" + ToolsName + @"\Set";
            string value = Registry.RegistryStrValue(key, "文件更新");
 
            if (!value.Contains(info) || !System.IO.File.Exists(file1))
            {
                Registry.RegistrySave(key, "文件更新", info);
 
                // UpdateFiles.exe文件资源 https://git.oschina.net/scimence/UpdateFiles/raw/master/files/UpdateFiles.exe
                Byte[] array = Properties.Resources.UpdateFiles.ToArray<byte>();
                SaveFile(array, file1);
            }
        }
 
 
        /// <summary>
        /// 保存Byte数组为文件
        /// </summary>
        public static void SaveFile(Byte[] array, string path)
        {
            // 创建输出流
            System.IO.FileStream fs = new System.IO.FileStream(path, System.IO.FileMode.Create);
 
            //将byte数组写入文件中
            fs.Write(array, 0, array.Length);
            fs.Close();
        }
 
        /// <summary>
        /// 更新文件逻辑,判定文件是否处于运行状态,关闭并删除后,创建新的文件
        /// </summary>
        private static void outPutFile(Byte[] array, string pathName)
        {
            // 若文件正在运行,则从进程中关闭
            string fileName = System.IO.Path.GetFileName(pathName);
            KillProcess(fileName);
 
            // 删除原有文件
            if (System.IO.File.Exists(pathName)) System.IO.File.Delete(pathName);
 
            // 保存新的文件
            SaveFile(array, pathName);
        }
 
        /// <summary>
        /// 关闭名称为processName的所有进程
        /// </summary>
        public static void KillProcess(string processName)
        {
            Process[] processes = Process.GetProcessesByName(processName);
 
            foreach (Process process in processes)
            {
                if (process.MainModule.FileName == processName)
                {
                    process.Kill();
                }
            }
        }
 
        /// <summary>
        /// 获取应用的当前工作路径
        /// </summary>
        public static String curDir()
        {
            string CurDir = System.AppDomain.CurrentDomain.BaseDirectory;
            return CurDir;
        }
    }
 
 
 
    // ------------------------------------------------------------------------------------
 
 
    // 示例:scimence( Name1(6JSO-F2CM-4LQJ-JN8P) )scimence
    // string url = "https://git.oschina.net/scimence/easyIcon/wikis/OnlineSerial";
    //
    // string data = getWebData(url);
    // string str1 = getNodeData(data, "scimence", false);
    // string str2 = getNodeData(str1, "Name1", true);
 
    /// <summary>
    /// 此类用于获取,在网络文件中的配置信息
    /// </summary>
    class WebSettings
    {
        #region 网络数据的读取
 
        //从给定的网址中获取数据
        public static string getWebData(string url)
        {
            try
            {
                System.Net.WebClient client = new System.Net.WebClient();
                client.Encoding = System.Text.Encoding.Default;
                string data = client.DownloadString(url);
                return data;
            }
            catch (Exception) { return ""; }
        }
 
        #endregion
 
 
        // 从自定义格式的数据data中,获取nodeName对应的节点数据
        //p>scimence(
NeedToRegister(false)NeedToRegister
RegisterPrice(1)RegisterPrice
)scimence<p> </p>
 
        // NeedToRegister(false)
RegisterPrice(1)   finalNode的数据格式
        public static string getNodeData(string data, string nodeName, bool finalNode)
        {
            try
            {
                string S = nodeName + "(", E = ")" + (finalNode ? "" : nodeName);
                int indexS = data.IndexOf(S) + S.Length;
                int indexE = data.IndexOf(E, indexS);
 
                return data.Substring(indexS, indexE - indexS);
            }
            catch (Exception) { return data; }
        }
    }
 
 
 
    // ------------------------------------------------------------------------------------
 
 
    /// <summary>
    /// 此类用于实现对注册表的操作
    /// </summary>
    class Registry
    {
        # region 注册表操作
        //设置软件开机启动项: RegistrySave(@"Microsoft\Windows\CurrentVersion\Run", "QQ", "C:\\windows\\system32\\QQ.exe"); 
 
        /// <summary>
        /// 记录键值数据到注册表subkey = @"Scimence\Email\Set";
        /// </summary>
        public static void RegistrySave(string subkey, string name, object value)
        {
            //设置一个具有写权限的键 访问键注册表"HKEY_CURRENT_USER\Software"
            Microsoft.Win32.RegistryKey keyCur = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software", true);
            Microsoft.Win32.RegistryKey keySet = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\" + subkey, true);
            if (keySet == null) keySet = keyCur.CreateSubKey(subkey);   //键不存在时创建
 
            keySet.SetValue(name, value);   //保存键值数据
        }
 
        /// <summary>
        /// 获取注册表subkey下键name的字符串值
        /// <summary>
        public static string RegistryStrValue(string subkey, string name)
        {
            object value = RegistryValue(subkey, name);
            return value == null ? "" : value.ToString();
        }
 
        /// <summary>
        /// 获取注册表subkey下键name的值
        /// <summary>
        public static object RegistryValue(string subkey, string name)
        {
            Microsoft.Win32.RegistryKey keySet = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\" + subkey, true);
            return (keySet == null ? null : keySet.GetValue(name, null));
        }
 
        /// <summary>
        /// 判断注册表是否含有子键subkey
        /// <summary>
        public static bool RegistryCotains(string subkey)
        {
            Microsoft.Win32.RegistryKey keySet = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\" + subkey, true);
            return (keySet != null);
        }
 
        /// <summary>
        /// 判断注册表subkey下是否含有name键值信息
        /// <summary>
        public static bool RegistryCotains(string subkey, string name)
        {
            //设置一个具有写权限的键 访问键注册表"HKEY_CURRENT_USER\Software"
            Microsoft.Win32.RegistryKey keySet = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\" + subkey, true);
 
            if (keySet == null) return false;
            else return keySet.GetValueNames().Contains<string>(name);
        }
 
        /// <summary>
        /// 删除注册表subkey信息
        /// <summary>
        public static void RegistryRemove(string subkey)
        {
            //设置一个具有写权限的键 访问键注册表"HKEY_CURRENT_USER\Software"
            Microsoft.Win32.RegistryKey keyCur = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software", true);
            Microsoft.Win32.RegistryKey keySet = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\" + subkey, true);
 
            if (keySet != null) keyCur.DeleteSubKeyTree(subkey);      //删除注册表信息
        }
 
        /// <summary>
        /// 删除注册表subkey下的name键值信息
        /// <summary>
        public static void RegistryRemove(string subkey, string name)
        {
            //设置一个具有写权限的键 访问键注册表"HKEY_CURRENT_USER\Software"
            Microsoft.Win32.RegistryKey keySet = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\" + subkey, true);
            if (keySet != null) keySet.DeleteValue(name, false);
        }
 
        # endregion
    }
 
 
 
 
    // ------------------------------------------------------------------------------------
 
    // 示例:Program.cs
 
    //static class Program
    //{
    //    /// <summary>
    //    /// 应用程序的主入口点。
    //    /// </summary>
    //    [STAThread]
    //    static void Main()
    //    {
    //        ApplicationException.Run(call);     // 调用异常信息捕获类,进行异常信息的捕获
    //    }
 
    //    // 应用程序,入口逻辑
    //    public static void call()
    //    {
    //        Application.EnableVisualStyles();
    //        Application.SetCompatibleTextRenderingDefault(false);
 
    //        if (Update.Updated())
    //        {
    //            DependentFiles.checksAll();     // 检测工具运行依赖文件
    //            ToolSetting.Instance();         // 载入工具的配置信息
 
    //            Application.Run(new Form4());
    //        }
    //    }
 
    //}
 
    /// <summary>
    /// 此类用于捕获Application异常信息
    /// </summary>
    class ApplicationException
    {
        /// <summary>
        /// 定义委托接口处理函数,调用此类中的Main函数为应用添加异常信息捕获
        /// </summary>
        public delegate void ExceptionCall();
 
        public static void Run(ExceptionCall exCall)
        {
            try
            {
                //设置应用程序处理异常方式:ThreadException处理
                Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
                //处理UI线程异常
                Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
                //处理非UI线程异常
                AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
 
                if (exCall != null) exCall();
            }
            catch (Exception ex)
            {
                string str = GetExceptionMsg(ex, string.Empty);
                MessageBox.Show(str, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
 
 
        static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
        {
            string str = GetExceptionMsg(e.Exception, e.ToString());
            MessageBox.Show(str, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
 
            //bool ok = (MessageBox.Show(str, "系统错误,提交bug信息?", MessageBoxButtons.OKCancel, MessageBoxIcon.Error) == DialogResult.OK);
            //if (ok) sendBugToAuthor(str);
 
            Update.Updated();      // 捕获运行异常后,检测是否有版本更新
            //LogManager.WriteLog(str);
        }
 
        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            string str = GetExceptionMsg(e.ExceptionObject as Exception, e.ToString());
            MessageBox.Show(str, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
 
            //bool ok = (MessageBox.Show(str, "系统错误,提交bug信息?", MessageBoxButtons.OKCancel, MessageBoxIcon.Error) == DialogResult.OK);
            //if (ok) sendBugToAuthor(str);
 
            Update.Updated();      // 捕获运行异常后,检测是否有版本更新
            //LogManager.WriteLog(str);
        }
 
        /// <summary>
        /// 生成自定义异常消息
        /// </summary>
        ///<param name="ex">异常对象
        ///<param name="backStr">备用异常消息:当ex为null时有效
        /// <returns>异常字符串文本</returns>
        static string GetExceptionMsg(Exception ex, string backStr)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("****************************异常文本****************************");
            sb.AppendLine("【出现时间】:" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"));
            if (ex != null)
            {
                sb.AppendLine("【异常类型】:" + ex.GetType().Name);
                sb.AppendLine("【异常信息】:" + ex.Message);
                sb.AppendLine("【堆栈调用】:" + ex.StackTrace);
                sb.AppendLine("【异常方法】:" + ex.TargetSite);
            }
            else
            {
                sb.AppendLine("【未处理异常】:" + backStr);
            }
            sb.AppendLine("***************************************************************");
 
 
            Update.Updated();      // 捕获运行异常后,检测是否有版本更新
 
            return sb.ToString();
        }
    }
}</summary></summary></summary></summary></string></summary></summary></summary></summary></summary></summary></summary></summary></byte>

   

 

将Update.exe修改后缀名,作为Resource资源添加到工程中

 

在Update.cs中指定versionInfo.txt文件,在versionInfo.txt设定工具在线更新地址。update.exe在运行时,会自动检测版本信息并更新。

 

以上就介绍了C#.NET的相关知识,希望对C#.NET有兴趣的朋友有所帮助。了解更多内容,请关注职坐标编程语言C#.NET频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程