第一次写博客, 如有错误, 请大家及时告知, 本人立即改之.
如果您有好的想法或者建议, 我随时与我联系.
如果发现代码有误导时, 请与我联系, 我立即改之.
好了不多说, 直接贴代码.
一般的错误, 使用下面三个就可以了. 我不太赞同项目里面大量使用 try{}catch{}(释放资源除外)
- // 设置 UI 线程发生异常时处理函数
- System.Windows.Application.Current.DispatcherUnhandledException += App_DispatcherUnhandledException;
- // 设置非 UI 线程发生异常时处理函数
- AppDomain.CurrentDomain.UnhandledException += App_CurrentDomainUnhandledException;
- // 设置托管代码异步线程发生异常时处理函数
- TaskScheduler.UnobservedTaskException += EventHandler_UnobservedTaskException;
特殊情况下, 此函数可检测到 c++ 封装的 dll(不是百分之百可以检测到)
- public delegate int CallBack(ref long a);
- CallBack myCall;
- [DllImport("kernel32")]
- private static extern Int32 SetUnhandledExceptionFilter(CallBack cb);
- // 设置非托管代码发生异常时处理函数
- callBack = new CallBack(ExceptionFilter);
- SetUnhandledExceptionFilter(callBack);
此函数可让程序 "美化" 结束.
完整代码:
- public partial class App : Application
- {
- [System.Runtime.InteropServices.DllImport("kernel32")]
- private static extern Int32 SetUnhandledExceptionFilter(CallBack cb);
- private delegate int CallBack(ref long a);
- private CallBack callBack;
- private System.Threading.Mutex mutex;
- public App()
- {
- Startup += new System.Windows.StartupEventHandler(App_Startup);
- }
- private void App_Startup(object sender, System.Windows.StartupEventArgs e)
- {
- mutex = new System.Threading.Mutex(true, $"{System.Reflection.Assembly.GetEntryAssembly().GetName().Name} - 8F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE8F", out bool ret);
- if (!ret)
- {
- System.Windows.MessageBox.Show($"{System.Reflection.Assembly.GetEntryAssembly().GetName().Name} has already started up.",
- "App_Startup",
- System.Windows.MessageBoxButton.OK,
- System.Windows.MessageBoxImage.Information);
- Environment.Exit(0);
- return;
- }
- Log4net.Init(typeof(MainWindow));
- // 设置 UI 线程发生异常时处理函数
- System.Windows.Application.Current.DispatcherUnhandledException += App_DispatcherUnhandledException;
- // 设置非 UI 线程发生异常时处理函数
- AppDomain.CurrentDomain.UnhandledException += App_CurrentDomainUnhandledException;
- // 设置非托管代码发生异常时处理函数
- callBack = new CallBack(ExceptionFilter);
- SetUnhandledExceptionFilter(callBack);
- // 设置托管代码异步线程发生异常时处理函数
- TaskScheduler.UnobservedTaskException += EventHandler_UnobservedTaskException;
- }
- void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
- {
- Log4net.gLogger.Error("--<App_DispatcherUnhandledException>--" + e.Exception.ToString());
- System.Windows.Forms.MessageBox.Show(e.Exception.ToString(),
- "Error",
- System.Windows.Forms.MessageBoxButtons.OK,
- System.Windows.Forms.MessageBoxIcon.Error);
- e.Handled = true;
- }
- void App_CurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
- {
- Log4net.gLogger.Fatal("--<App_CurrentDomainUnhandledException>--" + e.ExceptionObject.ToString());
- if (System.Windows.Forms.DialogResult.Yes
- == System.Windows.Forms.MessageBox.Show(
- "软件出现不可恢复错误, 即将关闭. 是否选择生成 Dump 文件以供开发人员分析问题?",
- "Error", System.Windows.Forms.MessageBoxButtons.YesNo,
- System.Windows.Forms.MessageBoxIcon.Error, System.Windows.Forms.MessageBoxDefaultButton.Button1))
- {
- WriteDump();
- }
- Environment.Exit(0);
- }
- private int ExceptionFilter(ref long a)
- {
- Log4net.gLogger.Fatal("--<ExceptionFilter>--" + Environment.StackTrace);
- WriteDump();
- return 1;
- }
- private void WriteDump()
- {
- Dump.WriteDumpFile();
- }
- }
对于一些问题, 我们可以通过日志文件记录(我目前使用 Log4net). 有时候日志不能完全帮助我们找到问题所在, 这时 dmp 文件就可以帮助到我们.
- internal class DumpWriter
- {
- public enum MiniDumpType
- {
- None = 0x00010000,
- 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
- }
- [DllImport("DbgHelp.dll")]
- private static extern bool MiniDumpWriteDump(
- IntPtr hProcess,
- Int32 processId,
- IntPtr fileHandle,
- MiniDumpType dumpType,
- ref MiniDumpExceptionInformation excepInfo,
- IntPtr userInfo,
- IntPtr extInfo);
- [DllImport("DbgHelp.dll")]
- private static extern bool MiniDumpWriteDump(
- IntPtr hProcess,
- Int32 processId,
- IntPtr fileHandle,
- MiniDumpType dumpType,
- IntPtr excepParam,
- IntPtr userInfo,
- IntPtr extInfo);
- [StructLayout(LayoutKind.Sequential, Pack = 4)]// Pack=4 is important! So it works also for x64!
- private struct MiniDumpExceptionInformation
- {
- public uint ThreadId;
- public IntPtr ExceptionPointers;
- [MarshalAs(UnmanagedType.Bool)]
- public bool ClientPointers;
- }
- [DllImport("kernel32.dll")]
- private static extern uint GetCurrentThreadId();
- private bool WriteDump(String dmpPath, MiniDumpType dmpType)
- {
- using (FileStream stream = new FileStream(dmpPath, FileMode.Create))
- {
- // 取得进程信息
- Process process = Process.GetCurrentProcess();
- MiniDumpExceptionInformation mei = new MiniDumpExceptionInformation();
- mei.ThreadId = GetCurrentThreadId();
- mei.ExceptionPointers = Marshal.GetExceptionPointers();
- mei.ClientPointers = true;
- bool res = false;
- // 如果不使用 MiniDumpWriteDump 重载函数
- // 当 mei.ExceptioonPointers == IntPtr.Zero => 无法保存 dmp 文件
- // 且当 mei.ClientPointers == false 时程序直接崩溃(mei.ClientPointers == true 程序不崩溃)
- //
- // 以上测试信息硬件环境 CPU Pentium(R) Dual-Core CPU T4200 @ 2.00GHz
- // vs2013update5
- // 在公司服务器上测试 (64 位系统, vs2013) 不会出现上述情况
- /*res = MiniDumpWriteDump(
- process.Handle,
- process.Id,
- stream.SafeFileHandle.DangerousGetHandle(),
- dmpType,
- ref mei,
- IntPtr.Zero,
- IntPtr.Zero);*/
- if (mei.ExceptionPointers == IntPtr.Zero)
- {
- res = MiniDumpWriteDump(
- process.Handle,
- process.Id,
- stream.SafeFileHandle.DangerousGetHandle(),
- dmpType,
- IntPtr.Zero,
- IntPtr.Zero,
- IntPtr.Zero);
- }
- else
- {
- res = MiniDumpWriteDump(
- process.Handle,
- process.Id,
- stream.SafeFileHandle.DangerousGetHandle(),
- dmpType,
- ref mei,
- IntPtr.Zero,
- IntPtr.Zero);
- }
- return res;
- }
- }
- public DumpWriter()
- {
- FilePath = Environment.CurrentDirectory + @"\Dump";
- if (!Directory.Exists(FilePath))
- Directory.CreateDirectory(FilePath);
- }
- /// <summary>
- /// 保存 dmp 文件路径
- /// </summary>
- public string FilePath { get; protected set; }
- /// <summary>
- /// 保存 dmp 文件名称(包括路径)
- /// </summary>
- public string FileName { get; protected set; }
- /// <summary>
- /// 写 dmp 文件
- /// </summary>
- /// <param name="dmpType">参数, 不同参数保存内容不一样</param>
- /// <returns></returns>
- public bool WriteDumpFile(MiniDumpType dmpType)
- {
- FileName = string.Format("{0}\\{1}_{2}.dmp",
- FilePath,
- DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss-fff"),
- Process.GetCurrentProcess().ProcessName);
- return WriteDump(FileName, dmpType);
- }
- }
好了, 就写这么多吧. 一般情况下, 这些应该可以帮助我们解决大部分问题了.
来源: http://www.bubuko.com/infodetail-3184692.html