程序启动添加全局异常捕获和Dump日志记录

发布时间 2024-01-04 15:36:46作者: 码农阿亮

Dump日志记录

  /// <summary>
  /// 功能描述:程序全局异常捕获Dump文件记录
  /// </summary>
  public static class MiniDump
  {
      [Flags]
      public enum Option : uint
      {
          // From dbghelp.h:
          Normal = 0x00000000,
          WithDataSegs = 0x00000001,
          WithFullMemory = 0x00000002,
          WithHandleData = 0x00000004,
          FilterMemory = 0x00000008,
          ScanMemory = 0x00000010,
          WithUnloadedModules = 0x00000020,
          WithIndirectlyReferencedMemory = 0x00000040,
          FilterModulePaths = 0x00000080,
          WithProcessThreadData = 0x00000100,
          WithPrivateReadWriteMemory = 0x00000200,
          WithoutOptionalData = 0x00000400,
          WithFullMemoryInfo = 0x00000800,
          WithThreadInfo = 0x00001000,
          WithCodeSegs = 0x00002000,
          WithoutAuxiliaryState = 0x00004000,
          WithFullAuxiliaryState = 0x00008000,
          WithPrivateWriteCopyMemory = 0x00010000,
          IgnoreInaccessibleMemory = 0x00020000,
          ValidTypeFlags = 0x0003ffff,
      }

      enum ExceptionInfo
      {
          None,
          Present
      }

      [StructLayout(LayoutKind.Sequential, Pack = 4)]  // Pack=4 is important! So it works also for x64!
      struct MiniDumpExceptionInformation
      {
          public uint ThreadId;
          public IntPtr ExceptionPointers;
          [MarshalAs(UnmanagedType.Bool)]
          public bool ClientPointers;
      }

      [DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]

      static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, ref MiniDumpExceptionInformation expParam, IntPtr userStreamParam, IntPtr callbackParam);

      //Overload supporting MiniDumpExceptionInformation == NULL
      [DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
      static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, IntPtr expParam, IntPtr userStreamParam, IntPtr callbackParam);

      [DllImport("kernel32.dll", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)]
      static extern uint GetCurrentThreadId();

      static bool Write(SafeHandle fileHandle, Option options, ExceptionInfo exceptionInfo)
      {
          Process currentProcess = Process.GetCurrentProcess();
          IntPtr currentProcessHandle = currentProcess.Handle;
          uint currentProcessId = (uint)currentProcess.Id;
          MiniDumpExceptionInformation exp;
          exp.ThreadId = GetCurrentThreadId();
          exp.ClientPointers = false;
          exp.ExceptionPointers = IntPtr.Zero;
          if (exceptionInfo == ExceptionInfo.Present)
          {
              exp.ExceptionPointers = Marshal.GetExceptionPointers();
          }
          return exp.ExceptionPointers == IntPtr.Zero ? MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint)options, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero) : MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint)options, ref exp, IntPtr.Zero, IntPtr.Zero);
      }

      static bool Write(SafeHandle fileHandle, Option dumpType)
      {
          return Write(fileHandle, dumpType, ExceptionInfo.None);
      }

      public static Boolean TryDump(String dmpPath, Option dmpType = Option.Normal)
      {
          var path = Path.Combine(Environment.CurrentDirectory, dmpPath);
          var dir = Path.GetDirectoryName(path);
          if (dir != null && !Directory.Exists(dir))
          {
              Directory.CreateDirectory(dir);
          }
          using (var fs = new FileStream(path, FileMode.Create))
          {
              return Write(fs.SafeFileHandle, dmpType);
          }
      }
  }

程序启动添加全局异常捕获

//同步基元
 private static System.Threading.Mutex mutex;
 protected override void OnStartup(StartupEventArgs e)
 {
     mutex = new System.Threading.Mutex(true, "App");
     if (mutex.WaitOne(0, false))
     {
         base.OnStartup(e);
         DispatcherUnhandledException += App_DispatcherUnhandledException;
         TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
     }
     else { MessageBox.Show("程序已经在运行!", "警告", MessageBoxButton.OK, MessageBoxImage.Information); this.Shutdown(); }
 }


 private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
 {
     try
     {
         e.Handled = true;
         //记录异常日志信息
     }
     catch (Exception ex)
     {
           //记录异常日志信息
     }
 }
 private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
 {
     try
     {
        //记录异常日志信息
         e.SetObserved();
     }
     catch (Exception ex)
     {
          //记录异常日志信息
     }
 }
 private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
 {
     try
     {
         if (e.ExceptionObject is Exception ex)
             //记录异常日志信息
         else
         {
               //记录异常日志信息
         }
         //记录dump文件
         MiniDump.TryDump($"dumps\\App_{DateTime.Now.ToString("HH-mm-ss-ms")}.dmp");
     }
     catch (Exception ex)
     {
           //记录异常日志信息
     }
 }