转发自:http://www.cnblogs.com/HouZhiHouJueBlogs/p/3951815.html

  我们知道,.Net的应用程序运行在.net framework虚拟机上,对于在运行时发生的错误,我们有try...catch可以捕捉,实在不济,对于winform和asp.net 我们都有全局的事件可以订阅处理。具体请参见:http://www.cnblogs.com/eaglet/archive/2009/02/17/1392191.html ,但是如果不通过.net Framework,而是直接通过P/Invoke调用操作系统的C/C++写的库,而不是通过.Net Framework的BCL调用操作系统功能,那么上面链接所说的方法便失去作用。譬如我有一个方法:

 [DllImport("kernel32")]private static extern void RtlMoveMemory(IntPtr dst, ref byte src, Int32 len);

然后我们拖个按钮,写个事件:

 private void button1_Click(object sender, EventArgs e){byte a = 0;RtlMoveMemory(IntPtr.Zero, ref a, 1);}

程序会直接崩溃,用上述的方法无论如何都捕捉不到的。不信您可以试试。

那怎么办?解铃还须系铃人。你直接调用操作系统API,难道操作系统没有提供异常捕获机制么?有的。现在我们引入几个术语。

术语:
SEH: 结构化异常处理
VEH: 向量化异常处理
TopLevelEH:顶层异常处理

相信写过C或者C++程序的同学可能不会陌生。现在我们介绍当用P/Invoke调用出现异常时,操作系统的异常处理顺序流程:

1. 交给调试器(前提是进程必须被调试)
2. 执行VEH
3. 执行SEH
4. TopLevelEH(进程被调试时不会被执行)
5. 交给调试器(上面的异常处理都说处理不了,就再次交给调试器)
6. 调用异常端口通知csrss.exe

下面咱就详细讨论一下各个步骤都干了哪些细活:

1. 第一次交给调试器
 
 如果该出现异常的程序正在被调试,则该异常首先交给调试器处理(通过DebugPort)。调试器拿到这个异常后,需要判断是否要处理该异常.

2. 执行VEH
 
这里就不讲Veh的概念了,有兴趣的去Google一下。
 如果没有被调试,或者调试器返回DBG_EXCEPTION_NOT_HANDLED,则就会检查是否存在VEH。如果存在VEH,则把异常交给他们处理。
 VEH是个链表,可以存在多个Veh。每个VEH按顺序被调用。
 一个VEH可以返回连个值:EXCEPTION_CONTINUE_SEARCH、EXCEPTION_CONTINUE_EXECUTION。返回                          EXCEPTION_EXECUTE_HANDLER是无效的,等同于EXCEPTION_CONTINUE_SEARCH。                       
 当一个Veh返回EXCEPTION_CONTINUE_SEARCH,则把异常交给下一个VEH处理。
 如果返回EXCEPTION_CONTINUE_EXECUTION,认为已经被处理,退出异常处理器在异常指令处继续执行。
 从执行顺序来看,VEH是在SEH之前执行的,并且不依赖某一线程,本进程中任何线程出现异常都可以被VEH处理,所以在有些时候是很有用处的。

那么怎么添加一个VEH呢?这里不是我们介绍的重点,请参考:http://msdn.microsoft.com/en-us/library/ms681420%28VS.85%29.aspx

3. 执行SEH
 
SEH是基于线程栈的异常处理机制。当所有的VEH都不处理该异常,该异常就会让SEH处理,所以它只能处理自己线程的异常。

4. TopLevelEH

  顶层异常处理,这个就是我们今天介绍的重点了,这个其实是利用SEH实现的。在最顶层的SEH中,可以注册一个顶层异常处理器。虽然他是基于SEH实现的,但是它可以处理所有线程抛出的异常。
当SEH都处理不了该异常,在最顶层的SEH中就会检查是否注册了顶层异常处理,如果注册了,则执行顶层异常处理。
注意:如果该进程正在调试状态,顶层异常处理会被忽略,不会被执行。
顶层异常处理函数也可以返回三个值:EXCEPTION_CONTINUE_SEARCH、EXCEPTION_EXECUTE_HANDLER、EXCEPTION_CONTINUE_EXECUTION,先记着,等会有用。  

  这个到底有什么用呢?应用程序难免会出现崩溃的,一旦崩溃了怎么办?想想QQ,每次崩溃都会弹出友好提示,它是怎么做到的呢?对了,就是这个TopLevelEH。

关于这个,某java开发的同学其实已经申请了专利:

公开号    CN101794243 A
发布类型    申请
专利申请号    CN 201010126856
公开日    2010年8月4日
申请日期    2010年3月18日
优先权日    2010年3月18日摘要:
一种利用操作系统结构化异常处理加固java应用程序的方法
CN 101794243 A本发明提供一种利用操作系统结构化异常处理加固java应用程序的方法,Java提供了在java程序中调用本地程序的方法,这些本地程序通常以动态库的形式存在,一旦动态库中出现没有捕获的错误,就会导致整个java虚拟机崩溃,并且没有任何补救方法。通过利用操作系统的结构化异常处理机制,能保证java虚拟机在崩溃以后按照需要执行相应的补救措施,比如发出友好化的通知,重新启动java虚拟机等。

看看,人家java的Jni(就是java中调用本地链接库的方法,对应于.net的P/Invoke)也同样遇到了这个问题,然后。。然后就专利了还,好吧这个专利太简单,我送给.net的同学们好了。

该专利被华为引用:

公开号    WO2013071766 A1
发布类型    申请
专利申请号    PCT/CN2012/078524
公开日    2013年5月23日
申请日期    2012年7月12日
优先权日    2011年11月14日
公告号    CN103107905A, EP2712119A1, US20140115587
申请人    Huawei Technologies Co., Ltd., 华为技术有限公司摘要:
本发明公开了一种异常处理方法、装置和客户端,属于在线应用领域。该方法包括:虚拟管理服务器接收与第一客户端交互的虚拟机发送的异常通知,所述异常通知至少携带用户标识和应用标识;所述虚拟管理服务器根据保存的与所述用户标识及应用标识对应的异常处理方式,保存所述虚拟机数据或与所述应用标识对应的应用的应用数据,并释放所述虚拟机资源。该装置包括:接收模块和异常处理模块。本发明使得不同应用、不同用户可以根据其需求定制不同的异常处理方法,也使得客户端不但可保存异常发生时的时刻或最接近异常发生时的时刻用户的使用状态,而且提高了在线应用系统的容量和效率。

说白了就是捕捉到异常之后发消息而已啦,其实所谓的专利就是这么简单的东西。

 关于5和6我们就略过好了,讲讲大家都关心的怎么来实现吧。

首先定义一个委托:

 public delegate Int32 CallBack(ref long a);CallBack mycall;

注册一个顶层异常处理器的方法如下:

[DllImport("kernel32")]private static extern Int32 SetUnhandledExceptionFilter(CallBack cb);

在系统初始化时,调用:

mycall = new CallBack(MyExceptionfilter);
SetUnhandledExceptionFilter(mycall);

MyExceptionfilter签名如下:
Int32 MyExceptionfilter(ref long a)

它返回一个Int值,对应上面的TopLevelEH:

EXCEPTION_EXECUTE_HANDLER == 1 表示我已经处理了异常,可以优雅地结束了 
EXCEPTION_CONTINUE_SEARCH == 0 表示我不处理,其他人来吧,于是windows调用默认的处理程序显示一个错误框,并结束 
EXCEPTION_CONTINUE_EXECUTION e== -1 表示错误已经被修复,请从异常发生处继续执行。

在实际方法中,你可以记录下程序的dump文件(Dump文件有什么用?回头我再写一篇好了),发送消息,然后优雅的结束或者重启,做出极好的客户体验,是不是很棒?!接下来我们处理开头的异常,那其实很简单了,必定会被捕获到,不信您可以试试。

代码实在很简单,我就不上传了,有心的同学一试就出来了。

觉得写得好,您就点个赞~

参考链接:http://bbs.pediy.com/showthread.php?t=173853

转载于:https://www.cnblogs.com/aochulai/p/3953285.html

.net p/invoke 异常处理相关推荐

  1. spring beancopier Cannot invoke “Object.getClass()“ because “cause“ is null异常处理

    我们项目用到spring beancopier, 在别的机器上运行正常,代码拉到我机器上就不正常了,抛出异常信息如题. Caused by: org.springframework.beans.Bea ...

  2. JSP 异常处理如何处理?

    当编写JSP程序的时候,程序员可能会遗漏一些BUG,这些BUG可能会出现在程序的任何地方. JSP代码中通常有以下几类异常: 检查型异常:检查型异常就是一个典型的用户错误或者一个程序员无法预见的错误. ...

  3. aspnetcore mvc 异常处理_深入探究ASP.NET Core异常处理中间件

    前言 全局异常处理是我们编程过程中不可或缺的重要环节.有了全局异常处理机制给我们带来了很多便捷,首先我们不用满屏幕处理程序可能出现的异常,其次我们可以对异常进行统一的处理,比如收集异常信息或者返回统一 ...

  4. controller requestparam不传参数空指针异常_看完这篇文章,让你轻松学会Java异常处理...

    一.背景 最近专门负责团队的项目质量.我在治理异常日志过程中,总结了一下Java的异常处理.上面是我整理的最近自己比较常见的异常知识地图. 二.异常知识地图概述 从异常知识地图最左边的根开始看,地图从 ...

  5. java异常处理学习总结

    Java异常的栈轨迹(Stack Trace) 捕获到异常时,往往需要进行一些处理.比较简单直接的方式就是打印异常栈轨迹Stack Trace.说 起栈轨迹,可能很多人和我一样,第一反应就是print ...

  6. Asp.Net Core异常处理整理

    目前版本是Asp.Net Core v1.1,这个版本的感觉对Http请求中的错误处理方便不是很完善. 没有HttpException异常类,不能在任何的地方自由的抛出对应的异常状态. 一.默认的异常 ...

  7. 【struts2+hibernate+spring项目实战】统一异常处理(ssh)

    一.概述 在项目中总会出现各种异常.bug,为了使得用户体验更好,当系统出现异常的时候,我们需要有我们的处理方式,使得用户能够理解系统出现了什么问题. 二.异常类 首先我们需要编写一个异常类 pack ...

  8. Spring Boot Spring MVC异常处理原理分析

    一.Spring MVC为处理异常的前期准备 DispatcherServlet 入口类,是一个Servlet,是所有请求的分发点 初始化 DispatcherServlet在初始化时会触发onRef ...

  9. ARM 之十二 Cortex-M 内核异常处理、异常定位方法、在线调试、Keil MDK-ARM 的使用

      Cortex-M 内核本身提供了非常强大的异常处理机制.它可以非常有效的捕捉非法的内存访问以及其他一些异常.而我们常用的开发工具的异常处理就是使用了 Cortex-M 核的异常处理机制.   在 ...

最新文章

  1. 论文: Data-Driven Evolutionary Optimization: An Overview and case studies(1) 数据驱动概念,文章结构,大数分类
  2. C++11如何减少内存拷贝次数
  3. 乔布斯的斯坦福大学演讲:你必须要找到你所爱的东西
  4. go-ethereum-code-analysis 以太坊源码分析
  5. ADD_SHORTCUT_ACTION
  6. 789. 逃脱阻碍者
  7. 前端学习(3027):vue+element今日头条管理-关于图标的处理
  8. python eval函数格式_Python函数中eval函数知识点
  9. CentOS7 安装MongoDB 3.0服务
  10. 高性能Javascript HTML集合访问的学习笔记
  11. C# 错误 175: 具有固定名称“System.Data.SQLite.EF6”的 ADO.NET 提供程序未在计算机或应用程序配置文件中注册或无法加载
  12. 特斯拉CEO马斯克再卖4套房 挂牌价6250万美元
  13. python怎么用pip下载_python怎么用pip安装包
  14. linux 连接存储,在Linux中连接和使用云存储的三种途径
  15. Markdown语言调整图片居中、大小
  16. Java -- 新IO -- 目录
  17. Linux安全加固的常用方法
  18. 计算机二级c语言word答案,全国计算机考试二级C语言南开100题答案(Word版)
  19. 请画出使用mapreduce对英文句子_微信英文培训:50句出国旅行英语
  20. 图解“华为云潮汕火锅”的“牛里乾坤”

热门文章

  1. python调试_Python 调试
  2. vscode写python_vscode如何编写python?
  3. cmake 在安装mysql_cmake安装mysql
  4. python中合并列表_关于python:如何将两个列表合并到一个列表中?
  5. 手机相机里面的m_传玉晶光担任新款iphone后置相机广角、超广角镜头主要供应商...
  6. Python机器学习:SVM005SVM使用多项式特征
  7. 数据科学入门与实战:玩转pandas之七数据分箱技术,分组技术,聚合技术
  8. java构成对象的三要素_20155237 《JAVA程序设计》实验二(JAVA面向对象程序设计)实验报告...
  9. np.mean(data, axis=0)函数
  10. 教你如何在google上查阅一个方位的经纬度