• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

C#WinForm程序异常退出的捕获、继续执行与自动重启

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

本文参考网上搜索的信息,并做了适当修改可以让捕捉到异常之后阻止程序退出。

另给出了通过命令行自动重启的方法。

如果一个线程里运行除以零的计算,如下面的代码

        private void button1_Click(object sender, EventArgs e)
        {
            System.Threading.Thread t = new System.Threading.Thread(() =>
            {
                int a = 0;
                int c = 10 / a;
            });
            t.Start();
        }

 

将会导致程序自动结束,而且没有任何提示信息 但是如果是在主线程里运行这个代码,是会弹出异常信息对话框的

请问如何在线程里也出现这个异常信息对话框.或者避免程序直接退出,忽略异常,继续往下执行呢?
 
在WINFORM主线程捕获全部异常就行,如下代码:
            //处理未捕获的异常
            Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
            //处理UI线程异常
            Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
            //处理非UI线程异常
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
 最常出现的错误在 :UnhandledException 里出现。详细代码如下:
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main(string[] args) 
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            //处理未捕获的异常
            Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
            //处理UI线程异常
            Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
            //处理非UI线程异常
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

            Application.Run(new Form1(args));
            glExitApp = true;//标志应用程序可以退出
        }

        /// <summary>
        /// 是否退出应用程序
        /// </summary>
        static bool glExitApp = false;

        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            LogHelper.Save("CurrentDomain_UnhandledException", LogType.Error);
            LogHelper.Save("IsTerminating : " + e.IsTerminating.ToString(), LogType.Error);
            LogHelper.Save(e.ExceptionObject.ToString());

            while (true)
            {//循环处理,否则应用程序将会退出
                if (glExitApp) {//标志应用程序可以退出,否则程序退出后,进程仍然在运行
                    LogHelper.Save("ExitApp");
                    return; 
                }
                System.Threading.Thread.Sleep(2*1000);
            };
        }
        
        static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
        {
            LogHelper.Save("Application_ThreadException:" +
                e.Exception.Message, LogType.Error);
            LogHelper.Save(e.Exception);
            //throw new NotImplementedException();
        }
我自己稍微修改了点逻辑,你都懂的。
    static class Program
    {
        private static log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        /// <summary>
        /// 是否退出应用程序
        /// </summary>
        static bool glExitApp = false;


        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            _log.Info("程序启动");

            try
            {
                //处理未捕获的异常
                System.Windows.Forms.Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
                System.Windows.Forms.Application.ThreadException += Application_ThreadException;
                AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);

                Application.Run(new WebManager());
                glExitApp = true;
            }
            catch (Exception ex)
            {
                _log.Error(ex);
            }
            _log.Info("程序关闭");

        }


        private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            _log.Error("CurrentDomain_UnhandledException ==== IsTerminating : " + e.IsTerminating.ToString());
            _log.Error("e.ExceptionObject : " + e.ExceptionObject);
            _log.Error(e);
            if (e.IsTerminating)
            {
                Common.Globalparams.ShowMessageDialog("系统发生错误,请联系系统管理员,程序即将关闭。");
                //循环处理,否则应用程序将会退出
                if (glExitApp)
                {
                    //标志应用程序可以退出,否则程序退出后,进程仍然在运行
                    _log.Error("====ExitApp");
                    return;
                }
                System.Threading.Thread.Sleep(2 * 1000);
                _log.Error("====UnhandledException  While......");

                Common.StartupHelper.CmdStartSelf();
            }
        }

        private static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
        {
            var ex = e.Exception;
            if (ex != null)
            {
                _log.Error(ex);
            }
        }

    }
View Code

 如果程序需要重启只需要在捕获的事件处理时启动当前应用程序的代码即可。参考如下:

CmdStartCTIProc(Application.ExecutablePath, "cmd params");//放到捕获事件的处理代码后,重启程序,需要时加上重启的参数

        /// <summary>
        /// 在命令行窗口中执行
        /// </summary>
        /// <param name="sExePath"></param>
        /// <param name="sArguments"></param>
        static void CmdStartCTIProc(string sExePath, string sArguments)
        {
            Process p = new Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardInput = true;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.CreateNoWindow = false;
            p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
            p.Start();
            p.StandardInput.WriteLine(sExePath + " " + sArguments);
            p.StandardInput.WriteLine("exit");
            p.Close();

            System.Threading.Thread.Sleep(2000);//必须等待,否则重启的程序还未启动完成;根据情况调整等待时间
        }

 另外一种重启进程的方式:

            //重启程序,需要时加上重启的参数
            System.Diagnostics.ProcessStartInfo cp = new System.Diagnostics.ProcessStartInfo();
            cp.FileName = Application.ExecutablePath;
            cp.Arguments = "cmd params";
            cp.UseShellExecute = true;
            System.Diagnostics.Process.Start(cp);

完整代码:

    public class StartupHelper
    {
        /// <summary>
        /// 在命令行窗口中执行指定程序。(可以包括程序本身)
        /// </summary>
        /// <param name="exePath"></param>
        /// <param name="sArguments"></param>
        public static void CmdStartApp(string exePath, string sArguments)
        {
            System.Diagnostics.Process p = new System.Diagnostics.Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardInput = true;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.CreateNoWindow = false;
            p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
            p.Start();
            p.StandardInput.WriteLine(exePath + " " + sArguments);
            p.StandardInput.WriteLine("exit");
            p.Close();

            System.Threading.Thread.Sleep(2000);//必须等待,否则重启的程序还未启动完成;根据情况调整等待时间
        }

        /// <summary>
        /// 启动程序自己(一般程序异常退出时调用)
        /// </summary>
        /// <param name="strArguments"></param>
        public static void CmdStartSelf(string strArguments = "")
        {
            //重启程序,需要时加上重启的参数
            System.Diagnostics.ProcessStartInfo cp = new System.Diagnostics.ProcessStartInfo();
            cp.FileName = System.Windows.Forms.Application.ExecutablePath;
            cp.Arguments = strArguments;
            cp.UseShellExecute = true;
            System.Diagnostics.Process.Start(cp);

        }
    }
View Code

 

看了觉得有用的朋友,如果您方便的话,可以顶一下。谢谢!

 

 

出处:https://www.cnblogs.com/zaspring/archive/2013/04/16/3023927.html

本文参考网上搜索的信息,并做了适当修改可以让捕捉到异常之后阻止程序退出。

另给出了通过命令行自动重启的方法。

如果一个线程里运行除以零的计算,如下面的代码

        private void button1_Click(object sender, EventArgs e)
        {
            System.Threading.Thread t = new System.Threading.Thread(() =>
            {
                int a = 0;
                int c = 10 / a;
            });
            t.Start();
        }

 

将会导致程序自动结束,而且没有任何提示信息 但是如果是在主线程里运行这个代码,是会弹出异常信息对话框的

请问如何在线程里也出现这个异常信息对话框.或者避免程序直接退出,忽略异常,继续往下执行呢?
 
在WINFORM主线程捕获全部异常就行,如下代码:
            //处理未捕获的异常
            Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
            //处理UI线程异常
            Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
            //处理非UI线程异常
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
 最常出现的错误在 :UnhandledException 里出现。详细代码如下:
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main(string[] args) 
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            //处理未捕获的异常
            Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
            //处理UI线程异常
            Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
            //处理非UI线程异常
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

            Application.Run(new Form1(args));
            glExitApp = true;//标志应用程序可以退出
        }

        /// <summary>
        /// 是否退出应用程序
        /// </summary>
        static bool glExitApp = false;

        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            LogHelper.Save("CurrentDomain_UnhandledException", LogType.Error);
            LogHelper.Save("IsTerminating : " + e.IsTerminating.ToString(), LogType.Error);
            LogHelper.Save(e.ExceptionObject.ToString());

            while (true)
            {//循环处理,否则应用程序将会退出
                if (glExitApp) {//标志应用程序可以退出,否则程序退出后,进程仍然在运行
                    LogHelper.Save("ExitApp");
                    return; 
                }
                System.Threading.Thread.Sleep(2*1000);
            };
        }
        
        static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
        {
            LogHelper.Save("Application_ThreadException:" +
                e.Exception.Message, LogType.Error);
            LogHelper.Save(e.Exception);
            //throw new NotImplementedException();
        }
我自己稍微修改了点逻辑,你都懂的。
    static class Program
    {
        private static log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        /// <summary>
        /// 是否退出应用程序
        /// </summary>
        static bool glExitApp = false;


        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            _log.Info("程序启动");

            try
            {
                //处理未捕获的异常
                System.Windows.Forms.Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
                System.Windows.Forms.Application.ThreadException += Application_ThreadException;
                AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);

                Application.Run(new WebManager());
                glExitApp = true;
            }
            catch (Exception ex)
            {
                _log.Error(ex);
            }
            _log.Info("程序关闭");

        }


        private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            _log.Error("CurrentDomain_UnhandledException ==== IsTerminating : " + e.IsTerminating.ToString());
            _log.Error("e.ExceptionObject : " + e.ExceptionObject);
            _log.Error(e);
            if (e.IsTerminating)
            {
                Common.Globalparams.ShowMessageDialog("系统发生错误,请联系系统管理员,程序即将关闭。");
                //循环处理,否则应用程序将会退出
                if (glExitApp)
                {
                    //标志应用程序可以退出,否则程序退出后,进程仍然在运行
                    _log.Error("====ExitApp");
                    return;
                }
                System.Threading.Thread.Sleep(2 * 1000);
                _log.Error("====UnhandledException  While......");

                Common.StartupHelper.CmdStartSelf();
            }
        }

        private static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
        {
            var ex = e.Exception;
            if (ex != null)
            {
                _log.Error(ex);
            }
        }

    }
View Code

 如果程序需要重启只需要在捕获的事件处理时启动当前应用程序的代码即可。参考如下:

CmdStartCTIProc(Application.ExecutablePath, "cmd params");//放到捕获事件的处理代码后,重启程序,需要时加上重启的参数

        /// <summary>
        /// 在命令行窗口中执行
        /// </summary>
        /// <param name="sExePath"></param>
        /// <param name="sArguments"></param>
        static void CmdStartCTIProc(string sExePath, string sArguments)
        {
            Process p = new Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardInput = true;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.CreateNoWindow = false;
            p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
            p.Start();
            p.StandardInput.WriteLine(sExePath + " " + sArguments);
            p.StandardInput.WriteLine("exit");
            p.Close();

            System.Threading.Thread.Sleep(2000);//必须等待,否则重启的程序还未启动完成;根据情况调整等待时间
        }

 另外一种重启进程的方式:

            //重启程序,需要时加上重启的参数
            System.Diagnostics.ProcessStartInfo cp = new System.Diagnostics.ProcessStartInfo();
            cp.FileName = Application.ExecutablePath;
            cp.Arguments = "cmd params";
            cp.UseShellExecute = true;
            System.Diagnostics.Process.Start(cp);

完整代码:

    public class StartupHelper
    {
        /// <summary>
        /// 在命令行窗口中执行指定程序。(可以包括程序本身)
        /// </summary>
        /// <param name="exePath"></param>
        /// <param name="sArguments"></param>
        public static void CmdStartApp(string exePath, string sArguments)
        {
            System.Diagnostics.Process p = new System.Diagnostics.Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardInput = true;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.CreateNoWindow = false;
            p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
            p.Start();
            p.StandardInput.WriteLine(exePath + " " + sArguments);
            p.StandardInput.WriteLine("exit");
            p.Close();

            System.Threading.Thread.Sleep(2000);//必须等待,否则重启的程序还未启动完成;根据情况调整等待时间
        }

        /// <summary>
        /// 启动程序自己(一般程序异常退出时调用)
        /// </summary>
        /// <param name="strArguments"></param>
        public static void CmdStartSelf(string strArguments = "")
        {
            //重启程序,需要时加上重启的参数
            System.Diagnostics.ProcessStartInfo cp = new System.Diagnostics.ProcessStartInfo();
            cp.FileName = System.Windows.Forms.Application.ExecutablePath;
            cp.Arguments = strArguments;
            cp.UseShellExecute = true;
            System.Diagnostics.Process.Start(cp);

        }
    }
View Code

 

看了觉得有用的朋友,如果您方便的话,可以顶一下。谢谢!

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Effective C# Item38:定制和支持数据绑定发布时间:2022-07-13
下一篇:
C语言之局部变量&amp;全局变量&amp;变量存储方式发布时间:2022-07-13
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap