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

2021-12-10 13:42:45 浏览数 (1)

捕获异常

代码语言: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 = "rn----------------------"   DateTime.Now   " --------------------------rn"
        ex.Message
        "rn"
        ex.InnerException
        "rn"
        ex.StackTrace
        "rn----------------------footer--------------------------rn";
    try
    {
      //设置读写锁为写入模式独占资源,其他写入请求需要等待本次写入结束之后才能继续写入
      LogWriteLock.EnterWriteLock();
      File.AppendAllText(logpath, log);
    }
    finally
    {
      //退出写入模式,释放资源占用
      LogWriteLock.ExitWriteLock();
    }
  }
}

0 人点赞