wpf 单例模式和异常处理 (原发布 csdn 2017-04-12 20:34:12)
第一次写博客,如有错误,请大家及时告知,本人立即改之。
如果您有好的想法或者建议,我随时与我联系。
如果发现代码有误导时,请与我联系,我立即改之。
好了不多说,直接贴代码。
一般的错误,使用下面三个就可以了。我不太赞同项目里面大量使用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);
}
}
好了,就写这么多吧。一般情况下,这些应该可以帮助我们解决大部分问题了。
wpf 单例模式和异常处理 (原发布 csdn 2017-04-12 20:34:12)的更多相关文章
- WPF 启动页面 (原发布 csdn 2017-06-26 19:26:01)
如果我写的有误,请及时与我联系,我立即改之以免继续误导他/她人. 如果您有好的想法或者建议,请随时与我联系. wpf软件启动时,加载启动页面.软件初始化完成之后关闭页面. App.xaml.cs代码 ...
- 关于“关于C#装箱的疑问”帖子的个人看法 (原发布csdn 2017年10月07日 10:21:10)
前言 昨天晚上闲着无事,就上csdn逛了一下,突然发现一个帖子很有意思,就点进去看了一下. 问题很精辟 int a = 1; object b=a; object c = b; c = 2; 为什么b ...
- c# Equal函数 and 运算符'==' (原发布 csdn 2017年10月15日 20:39:26)
1.==.!=.<.>.<= 和>= 运算符为比较运算符(comparison operator).C#语言规范5.0中文版中比较运算符的描述如下: 2.通用类型系统 3.值类 ...
- WPF DataGrid显示MySQL查询信息,且可删除、修改、插入 (原发布 csdn 2018-10-13 20:07:28)
1.入行好几年了,工作中使用数据库几率很小(传统行业).借着十一假期回家机会,学习下数据库. 2.初次了解数据库相关知识,如果本文有误,还望告知. 3.本文主要目的,记录下wpf界面显示数据库信息,且 ...
- WPF DispatcherTimer一些个人看法 (原发布 csdn 2017-04-25 19:12:22)
wpf中的DispatcherTimer基本用法,本文不在叙述.主要写一些不同的,来提醒自己不要再犯同样错误. 前几天写代码时发现.当在非UI线程创建DispatcherTimer实例时,程序无法进入 ...
- IEEE浮点表示 (原发布 csdn 2018-10-14 10:29:33)
目录 观察IEEE浮点表示 工作中遇到过整型转浮点型(union那种转换),碰到就看下书,过后就遗忘了.等过段时间又出现此现象,又重新拿起书本,这次记录了过程.然而一直等到今天才写出来,以防以后还用到 ...
- c# 类实例序列化反序列化json文件 (原发布 csdn 2017-10-01 20:02:12)
前言 前段时间使用了net.json保存对象数据.添加完成后,测试发现300多实例数据保存加载json文件,速度比原方式(BinaryFormatter)慢.但是功能加上后也懒再删掉代码了,索性就采用 ...
- C# 流介绍 (原发布 csdn 2017-09-15 23:37:52)
1.FileStream FileStream 详细介绍参考msdn 写数据: using (FileStream fs = new FileStream("File.FileStream& ...
- datalab (原发布 csdn 2018年09月21日 20:42:54)
首先声明datalab本人未完成,有4道题目没有做出来.本文博客记录下自己的解析,以便以后回忆.如果能帮助到你就更好了,如果觉得本文没啥技术含量,也望多多包涵. /* * bitAnd - x& ...
随机推荐
- bzoj5093图的价值:多项式,斯特林数(二项式反演)
Description “简单无向图”是指无重边.无自环的无向图(不一定连通). 一个带标号的图的价值定义为每个点度数的k次方的和. 给定n和k,请计算所有n个点的带标号的简单无向图的价值之和. 因为 ...
- [译]Vulkan教程(17)帧缓存
[译]Vulkan教程(17)帧缓存 Framebuffers 帧缓存 We've talked a lot about framebuffers in the past few chapters a ...
- Java 添加Word页眉、页脚
本篇文章将介绍通过java程序来添加Word页眉页脚的方法.鉴于在不同文档中,对页眉页脚的操作要求不同,文章将分别从以下几种情况来阐述: 1.添加页眉页脚 添加图片到页眉 添加文本到页眉 添加页码 2 ...
- ADO.NET ORM数据库增删改查封装(工具一)
约束 public abstract class BaseModel { public int Id { get; set; } } 连接字符串 public static readonly stri ...
- PlayJava Day012
今日所学: /* 2019.08.19开始学习,此为补档. */ JPanel和JFrame 1.JFrame是最底层,JPanel是置于其面上,同一个界面只有一个JFrame,一个JFrame可以放 ...
- flutter 侧滑删除+侧滑显示删除按钮
1.侧滑删除 1.1.Dismissible组件 2.侧滑显示删除按钮 2.1.手势监听水平滑动 ------------------------------------分割线------------ ...
- OpenCV绘制直线,矩形和园
首先导入我们所需要的库: import numpy as np import cv2 import matplotlib.pyplot as plt 自定义显示图像的函数: def show(imag ...
- Gradle之FTP文件下载
Gradle之FTP文件下载 1.背景 项目上需要使用本地web,所以我们直接将web直接放入assets资源文件夹下.但是随着开发进行web包越来越大:所以我们想着从版本库里面去掉web将其忽略掉, ...
- 缺少控制文件备份时如何还原数据库 (Doc ID 1438776.1)
How to restore database when controlfile backup missing (Doc ID 1438776.1) APPLIES TO: Oracle Databa ...
- [内核同步]自旋锁spin_lock、spin_lock_irq 和 spin_lock_irqsave 分析【转】
转自:https://www.cnblogs.com/x_wukong/p/8573602.html 转自;https://www.cnblogs.com/aaronLinux/p/5890924.h ...