前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >WPF开发-全局异常捕获及日志记录

WPF开发-全局异常捕获及日志记录

作者头像
码客说
发布2021-12-10 13:42:45
1.6K1
发布2021-12-10 13:42:45
举报
文章被收录于专栏:码客码客

捕获异常

代码语言:javascript
复制
public partial class App : Application
{        
  protected override void OnStartup(StartupEventArgs e)
  {
    RegisterEvents();
    base.OnStartup(e);
  }

  private void RegisterEvents()
  {
    //Task线程内未捕获异常处理事件
    TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;//Task异常 

    //UI线程未捕获异常处理事件(UI主线程)
    DispatcherUnhandledException += App_DispatcherUnhandledException;

    //非UI线程未捕获异常处理事件(例如自己创建的一个子线程)
    AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
  }

  //Task线程内未捕获异常处理事件
  private static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
  {
    try
    {
      var exception = e.Exception as Exception;
      if (exception != null)
      {
        HandleException(exception);
      }
    }
    catch (Exception ex)
    {
      HandleException(ex);
    }
    finally
    {
      e.SetObserved();
    }
  }

  //非UI线程未捕获异常处理事件(例如自己创建的一个子线程)      
  private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
  {
    try
    {
      var exception = e.ExceptionObject as Exception;
      if (exception != null)
      {
        HandleException(exception);
      }
    }
    catch (Exception ex)
    {
      HandleException(ex);
    }
    finally
    {
      //ignore
    }
  }

  //UI线程未捕获异常处理事件(UI主线程)
  private static void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
  {
    try
    {
      HandleException(e.Exception);
    }
    catch (Exception ex)
    {
      HandleException(ex);
    }
    finally
    {
      e.Handled = true;
    }
  }

  //日志记录
  private static void HandleException(Exception ex)
  {
    MessageBox.Show("出错了,请与开发人员联系:"+ ex.Message);
    //记录日志
    LogHelper.WriteErrLog("未捕获异常:" + ex.Message, ex);
  }
}

日志记录

log4net

添加工具类

代码语言:javascript
复制
using log4net.Config;

using System;
using System.IO;

namespace Common.system
{
    public class LogHelper
    {
        public static readonly log4net.ILog loginfo = log4net.LogManager.GetLogger("loginfo");
        public static readonly log4net.ILog logerror = log4net.LogManager.GetLogger("logerror");

        public static void InitLog4Net()
        {
            var logCfg = new FileInfo(AppDomain.CurrentDomain.BaseDirectory + "log4net.config");
            XmlConfigurator.ConfigureAndWatch(logCfg);
            loginfo.Info("日志初始化");
        }

        public static void WriteInfoLog(string info)
        {
            if (loginfo.IsInfoEnabled)
            {
                loginfo.Info(info);
                Console.WriteLine(info);
            }
        }

        public static void WriteErrLog(string info, Exception ex)
        {
            if (logerror.IsErrorEnabled)
            {
                logerror.Error("[V " + FileToolsCommon.GetConfigValue("VersionName") + "]" + info, ex);
            }
        }
    }
}

项目根目录添加log4net.config

设置属性

配置如下:

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
  <!--错误日志类-->
  <logger name="logerror">
    <!--日志类的名字-->
    <level value="ALL" />
    <!--定义记录的日志级别-->
    <appender-ref ref="ErrorAppender" />
    <!--记录到哪个介质中去-->
  </logger>
  <!--信息日志类-->
  <logger name="loginfo">
    <level value="ALL" />
    <appender-ref ref="InfoAppender" />
  </logger>
  <!--错误日志附加介质-->
  <appender name="ErrorAppender" type="log4net.Appender.RollingFileAppender">
    <!-- name属性指定其名称,type则是log4net.Appender命名空间的一个类的名称,意思是,指定使用哪种介质-->
    <param name="File" value="Log\\LogError\\" />
    <!--日志输出到exe程序这个相对目录下-->
    <param name="AppendToFile" value="true" />
    <!--输出的日志不会覆盖以前的信息-->
    <param name="MaxSizeRollBackups" value="100" />
    <!--备份文件的个数-->
    <param name="MaxFileSize" value="10240" />
    <!--当个日志文件的最大大小-->
    <param name="StaticLogFileName" value="false" />
    <!--是否使用静态文件名-->
    <param name="DatePattern" value="yyyyMMdd&quot;.htm&quot;" />
    <!--日志文件名-->
    <param name="RollingStyle" value="Date" />
    <!--文件创建的方式,这里是以Date方式创建-->
    <!--错误日志布局-->
    <layout type="log4net.Layout.PatternLayout">
      <param name="ConversionPattern" value="&lt;HR COLOR=red&gt;%n异常时间:%d [%t] &lt;BR&gt;%n异常级别:%-5p &lt;BR&gt;%n异 常 类:%c [%x] &lt;BR&gt;%n%m &lt;BR&gt;%n" />
    </layout>
  </appender>
  <!--信息日志附加介质-->
  <appender name="InfoAppender" type="log4net.Appender.RollingFileAppender">
    <param name="File" value="Log\\LogInfo\\" />
    <param name="AppendToFile" value="true" />
    <param name="MaxFileSize" value="10240" />
    <param name="MaxSizeRollBackups" value="100" />
    <param name="StaticLogFileName" value="false" />
    <param name="DatePattern" value="yyyyMMdd&quot;.htm&quot;" />
    <param name="RollingStyle" value="Date" />
    <!--信息日志布局-->
    <layout type="log4net.Layout.PatternLayout">
      <param name="ConversionPattern" value="&lt;HR COLOR=blue&gt;%n日志时间:%d [%t] &lt;BR&gt;%n日志级别:%-5p &lt;BR&gt;%n日 志 类:%c [%x] &lt;BR&gt;%n%m &lt;BR&gt;%n" />
    </layout>
  </appender>
</log4net>

自定义日志类

代码语言:javascript
复制
class MyLogger{
  //读写锁,当资源处于写入模式时,其他线程写入需要等待本次写入结束之后才能继续写入
  private static readonly ReaderWriterLockSlim LogWriteLock = new ReaderWriterLockSlim();
  public static void LogWrite(Exception ex)
  {
    if (!Directory.Exists("Log"))
    {
      Directory.CreateDirectory("Log");
    }
    var now = DateTime.Now;
    var logpath = @"Log\" + now.Year + "" + now.Month + "" + now.Day + ".log";
    var log = "\r\n----------------------" + DateTime.Now + " --------------------------\r\n"
      + ex.Message
      + "\r\n"
      + ex.InnerException
      + "\r\n"
      + ex.StackTrace
      + "\r\n----------------------footer--------------------------\r\n";
    try
    {
      //设置读写锁为写入模式独占资源,其他写入请求需要等待本次写入结束之后才能继续写入
      LogWriteLock.EnterWriteLock();
      File.AppendAllText(logpath, log);
    }
    finally
    {
      //退出写入模式,释放资源占用
      LogWriteLock.ExitWriteLock();
    }
  }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-12-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 捕获异常
  • 日志记录
    • log4net
      • 自定义日志类
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档