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& ...
随机推荐
- gitlab-CI作业-yml
stages: - build - deploy before_script: - echo "Restore NuGet Packages..." - echo "do ...
- java之封装
java中通过将成员变量声明为private,再提供公共的public方法:setXxx()和getXxx()实现对该属性的操作,以实现以下目的: 隐藏一个类中不需要对外提供的实现: 使用者只能通过事 ...
- 软件文档写作-plantuml画用例图和时序图
背景 当下的软件开发人员,不可避免的需要输出一些软件设计文档,作为一个软件工程专业毕业的工程师,最常用的设计工具就是UML,使用UML工具绘制一些软件相关的图,是必备技能,也是输出的技术文档中的重要组 ...
- ZooKeeper(三):请求处理链路的创建过程解析
我们知道,zk就是一个个处理链组成的. 但是,这些处理链是在什么创建的呢? ZooKeeper 中有三种角色的服务节点存在: Leader, Follower, Observer . 而每个服务节点的 ...
- Selenium(八):其他操作元素的方法、冻结界面、弹出对话框、开发技巧
1. 其他操作元素的方法 之前我们对web元素做的操作主要是:选择元素,然后点击元素或者输入字符串. 还有没有其他的操作了呢?有. 比如:比如鼠标右键点击.双击.移动鼠标到某个元素.鼠标拖拽等. 这些 ...
- .Net Core MVC理解新管道处理模型、中间件
.Net Core中间件官网:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?view=aspnetcore ...
- 升鲜宝V2.0_杭州生鲜配送行业,再论B端生鲜配送企业管理软件的开发与实施的难点与行业痛点_15382353715_余东升
升鲜宝V2.0_杭州生鲜配送行业,再论B端生鲜配送企业管理软件的开发与实施的难点与行业痛点_15382353715_余东升 笔者简介:升鲜宝供应链管理软件平台创始人,14年软件从业经历,10多年深究生 ...
- 团队项目之Scrum2
小组:BLACK PANDA 时间:2019.11.17 每天举行站立式会议 提供当天站立式会议照片一张 2 昨天已完成的工作 2 确定用户登录与注册和编辑页面的接口 前端方面:详细确定页面的功能,并 ...
- SQL注入:POST注入
POST注入简介 POST注入属于注入的一种,相信大家在之前的课程中都知道POST\GET两种传参方式. POST注入就是使用POST进行传参的注入,本质上和GET类型的没什么区别. POST注入高危 ...
- 4. java 流程控制
一.判断语句 1. if 判断 if(关系表达式){ 语句体; } int age = 16; if(age >= 18){ System.out.println("hello&quo ...