VB.NET在WinCE5.0中异常转储试验

1.目的:

在CE系统上,当程序发生异常特别是不可重现的异常时,通过事后调试协助快速定位问题

 

2.原理:

在windows系统中,当应用程序出现严重错误无法运行时,系统会启动JIT调试器,JIT调试器可以做两类事情:1)直接附加到出错进程上通过调试来分析、定位问题。2)收集、记录错误发生时的现场数据提供事后分析。在WinCE上,希望利用第二种方式:也就是使用WER(Windwos Error Reporting)功能生成转储文件(dump文件)来进行事后分析。

 

 

3.实现

3.1捕获异常

转储文件是对特定进程、线程在内存中运行状态的快照,只有在异常发生时产生的快照才对我们查找问题有意义,因此首先需要捕获异常,捕获异常为我们生成转储文件提供了时机以及必要的上下文环境,例如只有在异常被捕获的状态下,Native的GetExceptionInformation和CLR的GetExceptionPointers才能获取到PEXCEPTION_POINTERS指针。我把捕获异常的方式分成3种:

3.1.1语法

编程语言都提供了异常捕获的语法关键字,例如对于C++和VB .NET:

C++ SEH

vb .net

__try __except

try catch

在try 块中发生异常以后,程序跳转到异常处理块中,在异常处理块中我们可以进行异常转储。


使用VB.NET的try catch得到异常转储的时机(仅仅是个时机)

 

3.1.2未处理异常过滤器或事件

Windows Native

Windows CLR

SetUnhandledExceptionFilter

Application..::.ThreadException  

_AppDomain..::.UnhandledException

 

l  SetUnhandledExceptionFilter

为一个应用的所有进程和线程设置一个顶级异常处理函数

l  Application..::.ThreadException

UI线程产生的异常处理事件

l  _AppDomain..::.UnhandledException

非UI线程产生的异常处理事件

 

WinCE不提供SetUnhandledExceptionFilter

cf .net 不提供Application..::.ThreadException和_AppDomain..::.UnhandledException

 

3.1.3 JIT调试

如果所有其它异常捕获机制都没有生效,系统根据注册表的设置尝试使用JIT调试器来分析问题。windows默认的jit调试器是Dr.Watson,它将为出错程序生成一个转储文件。

WinCE从5.0开始加入WER模块(windowserror reporting),也是为出错的程序生成转储文件。

这种方式下系统自动生成dump。

 

EVC程序可以生成dump,VB.NET程序无法生成dump。

 

 

3.2获取异常结构体指针

因为3.1.2和3.1.3都不可行,因此采用3.1.1的方式继续尝试。在捕获异常以后,要想保存转储文件,需要先获取异常结构指针。系统提供了以下函数

Windows  Native

Windows CLR

GetExceptionInformation

GetExceptionPointers

 

WinCE提供了GetExceptionInformation,但GetExceptionInformation并不是函数,而是一个宏,并且只允许在异常处理过滤表达式中调用,这意味着VB.NET代码无法通过P/Invoke调用GetExceptionInformation。

cf .net不提供GetExceptionPointers

结论是VB.NET无法获取异常结构体指针

3.3生成转储文件

在Windows中获取到正确的异常结构指针以后,就可以调用MiniDumpWriteDump保存转储文件,但是在CE5.0并没有MiniDumpWriteDump,它使用了CaptureDumpFileOnDevice和ReportFault。

Windows  Native

WinCE 5.0

MiniDumpWriteDump

CaptureDumpFileOnDevice

ReportFault

 

VB.NET适用性:

1.    虽然wince提供了ReportFault,但是因为3.2的结论,导致VB.NET无法调用ReportFault(异常结构指针参数无法获取)。

2.      CaptureDumpFileOnDevice通过试验可以产生dump,但是这个函数的参数是进程号和线程号,也就是说它无法保存异常发生时的状态。尝试了在VB.NET程序中P/InvokeCaptureDumpFileOnDevice,分析产生的dump文件发现堆栈信息缺少了托管代码的部分:

 

 

4.总结:

1)EVC程序既可以使用JIT也可以使用编程方式实现异常转储

2)VB.NET程序无法实现异常转储

你可能感兴趣的:(wince开发)