//==============================================================================
//
// 项目名 :
// 文件名 :XDBExceptionReport.h
// 作 者 :
// 用 途 :异常报告实现类。
//
//==============================================================================
// 版本记录
//==============================================================================
//
// V0.1 2005-5-19 9:30:47
// V0.9 2005-6-20 8:54:02 RC1
//
//==============================================================================
#ifndef __XDBEXCEPTIONREPORT__H__INCLUDED__
#define __XDBEXCEPTIONREPORT__H__INCLUDED__
//==============================================================================
//=============================================================
// 如果需要使用DBGHELP的Unicode版(要求DBGHELP 6.3以上),让下行生效
//=============================================================
// #define DBGHELP_TRANSLATE_TCHAR
//=============================================================
// 如果需要打印输出全局变量的信息,让下行生效
//=============================================================
// #define DBGHELP_PRINTOUT_GLOBAL
//=============================================================
// 必须的头文件
//=============================================================
#include <OAIdl.h> // VARIANT类型
#include <DbgHelp.h> // DBGHELP库
/// <summary>
/// 基本数据类型。
/// </summary>
/// <remarks>
/// 来源于DIA2.0 SDK的CVConst.h文件。
/// </remarks>
enum BasicType
{
btNoType = 0, /// 没有指定类型
btVoid = 1, /// void类型
btChar = 2, /// ANSI字符
btWChar = 3, /// UNICODE字符
btInt = 6, /// 有符号整数
btUInt = 7, /// 无符号整数
btFloat = 8, /// 浮点数
btBCD = 9, /// BCD类型
btBool = 10, /// 布尔值
btLong = 13, /// 有符号长整数
btULong = 14, /// 无符号长整数
btCurrency = 25, /// 货币类型
btDate = 26, /// 日期类型
btVariant = 27, /// 可变数据类型
btComplex = 28, /// 复数
btBit = 29, /// 二进制
btBSTR = 30, /// 字符串
btHresult = 31 /// HRESULT
};
/// <summary>
/// 基本符号类型。
/// </summary>
/// <remarks>
/// 来源于DIA2.0 SDK的CVConst.h文件。
/// </remarks>
enum SymTagType
{
SymTagNull, // 00:没有类型
SymTagExe, // 01:EXE文件
SymTagCompiland, // 02:对于本地程序,对应于0BJ文件;对于MSIL,情况会有不同
SymTagCompilandDetails, // 03:符号包含扩展的Compiland模块属性
SymTagCompilandEnv, // 04:符号是Compiland的环境字符串
SymTagFunction, // 05:函数
SymTagBlock, // 06:嵌套块
SymTagData, // 07:数据
SymTagAnnotation, // 08:代码注释
SymTagLabel, // 09:标号
SymTagPublicSymbol, // 10:公共(导出)符号
SymTagUDT, // 11:自定义类型
SymTagEnum, // 12:枚举
SymTagFunctionType, // 13:函数签名
SymTagPointerType, // 14:指针
SymTagArrayType, // 15:数组
SymTagBaseType, // 16:基本类型
SymTagTypedef, // 17:类型重定义(类型别名)
SymTagBaseClass, // 18:自定义类型的基类
SymTagFriend, // 19:自定义类型的友元
SymTagFunctionArgType, // 20:函数参数
SymTagFuncDebugStart, // 21:函数序幕代码的结束位置
SymTagFuncDebugEnd, // 22:函数结尾代码的开始位置
SymTagUsingNamespace, // 23:命名空间的名字
SymTagVTableShape, // 24:虚表描述
SymTagVTable, // 25:虚表指针
SymTagCustom, // 26:未解释的定制类型
SymTagThunk, // 27:THUNK
SymTagCustomType, // 28:定制编译器类型
SymTagManagedType, // 29:元数据
SymTagDimension, // 30:FORTRAN多维数组
SymTagMax // 31:符号类型的种类数目
};
/// <summary>
/// 异常报告实现类。
/// </summary>
class XDBExceptionReport
{
public:
/// <summary>
/// 构造函数。
/// </summary>
XDBExceptionReport( );
/// <summary>
/// 析构函数。
/// </summary>
~XDBExceptionReport( );
/// <summary>
/// 设置异常报告输出文件的路径。
/// </summary>
/// <param name="pszReportFileName">
/// 文件路径。
/// </param>
static void SetReportFileName( LPWSTR pszReportFileName );
/// <summary>
/// 获得异常报告输出文件的路径。
/// </summary>
/// <returns>
/// 返回文件路径。
/// </returns>
static WCHAR* GetReportFileName( );
/// <summary>
/// 未处理异常入口函数。
/// </summary>
/// <param name="pExceptionInfo">
/// 异常信息。
/// </param>
/// <returns>
/// 返回值为EXCEPTION_CONTINUE_SEARCH或EXCEPTION_EXECUTE_HANDLER。
/// </returns>
static LONG WINAPI XDBUnhandledExceptionFilter(
PEXCEPTION_POINTERS pExceptionInfo );
/// <summary>
/// 异常过滤函数。
/// </summary>
/// <param name="pszReportFileName">
/// 异常报告输出的文件路径。
/// </param>
/// <param name="pExceptionInfo">
/// 异常信息。
/// </param>
/// <param name="bWriteVariables">
/// 是否输出参数信息。
/// </param>
/// <returns>
/// 返回值为EXCEPTION_EXECUTE_HANDLER。
/// </returns>
static LONG WINAPI XDBHandledExceptionFilter(
LPCWSTR pszReportFileName,
PEXCEPTION_POINTERS pExceptionInfo,
bool bWriteVariables = false );
private:
/// <summary>
/// 生成异常报告。
/// </summary>
/// <param name="pReportFile">
/// 异常报告输出的文件句柄。
/// </param>
/// <param name="pExceptionInfo">
/// 异常信息。
/// </param>
/// <param name="bWriteVariables">
/// 是否输出参数信息。
/// </param>
static void GenerateExceptionReport(
HANDLE pReportFile,
PEXCEPTION_POINTERS pExceptionInfo,
bool bWriteVariables);
/// <summary>
/// 当文件尺寸过大时,收缩异常报告输出文件。
/// </summary>
/// <param name="pReportFile">
/// 异常报告输出文件句柄。
/// </param>
/// <param name="pszReportFileName">
/// 异常报告输出文件路径。
/// </param>
/// <returns>
/// 指明操作是否成功。
/// </returns>
static BOOL ShrinkReportFile(
HANDLE& pReportFile,
LPCWSTR pszReportFileName );
/// <summary>
/// 获得文件版本信息。
/// </summary>
/// <param name="lpszFileName">
/// 文件名。
/// </param>
/// <param name="lpszVersionName">
/// 要获取的版本信息。
/// </param>
/// <param name="lpszVersion">
/// 用于返回版本信息,必须具有足够的空间。
/// </param>
/// <returns>
/// 是否成功。
/// </returns>
static BOOL GetFileVersion(
LPCWSTR lpszFileName,
LPCWSTR lpszVersionName,
LPWSTR lpszVersion );
/// <summary>
/// 获得运行程序的版本信息。
/// </summary>
/// <param name="szBuffer">
/// 用于保存信息的缓冲区(必须足够大)。
/// </param>
/// <returns>
/// 返回程序信息。
/// </returns>
static WCHAR* GetApplicationInfo( WCHAR* szBuffer,size_t szLength );
/// <summary>
/// 获得异常代码的字符串描述。
/// </summary>
/// <param name="dwCode">
/// 异常代码。
/// </param>
/// <returns>
/// 异常代码的字符串描述。
/// </returns>
static WCHAR* GetExceptionString( DWORD dwCode );
/// <summary>
/// 获得引起异常的地址信息。
/// </summary>
/// <param name="addr">
/// 地址信息。
/// </param>
/// <param name="szModule">
/// 用于保存模块名的缓冲。
/// </param>
/// <param name="len">
/// 缓冲区大小。
/// </param>
/// <param name="section">
/// 地址所位于的节。
/// </param>
/// <param name="offset">
/// 地址偏移。
/// </param>
/// <returns>
/// 成功返回TRUE,否则返回FALSE。
/// </returns>
static BOOL GetLogicalAddress(
PVOID addr, PWSTR szModule, DWORD len,
DWORD_PTR& section, DWORD_PTR& offset );
/// <summary>
/// 输出调用堆栈信息。
/// </summary>
/// <param name="pReportFile">
/// 异常报告输出的文件句柄。
/// </param>
/// <param name="pContext">
/// 上下文环境句柄。
/// </param>
/// <param name="bWriteVariables">
/// 是否输出参数信息。
/// </param>
static void WriteStackDetails(
HANDLE pReportFile,
PCONTEXT pContext,
bool bWriteVariables );
/// <summary>
/// 枚举符号信息的回调函数。
/// </summary>
/// <param name="pSymInfo">
/// 符号信息。
/// </param>
/// <param name="SymbolSize">
/// 符号尺寸。
/// </param>
/// <param name="UserContext">
/// 用户参数。
/// </param>
/// <returns>
/// 返回TRUE时,继续枚举;否则,终止枚举过程。
/// </returns>
static BOOL CALLBACK EnumerateSymbolsCallback(
PSYMBOL_INFO pSymInfo,
ULONG SymbolSize,
PVOID UserContext );
/// <summary>
/// 格式化符号值。
/// </summary>
/// <param name="pSym">
/// 符号信息。
/// </param>
/// <param name="sf">
/// 堆栈帧。
/// </param>
/// <param name="pReportFile">
/// 异常报告输出的文件句柄。
/// </param>
/// <returns>
/// 成功或失败。
/// </returns>
static bool FormatSymbolValue(
PSYMBOL_INFO pSym,
LPSTACKFRAME64 sf,
HANDLE pReportFile );
/// <summary>
/// 输出类型信息。
/// </summary>
/// <param name="pReportFile">
/// 异常报告输出的文件句柄。
/// </param>
/// <param name="modBase">
/// 模块基址。
/// </param>
/// <param name="dwTypeIndex">
/// 类型索引。
/// </param>
/// <param name="nestingLevel">
/// 嵌套层次。
/// </param>
/// <param name="offset">
/// 偏移。
/// </param>
/// <returns>
/// 成功或失败标志。
/// </returns>
static bool DumpTypeIndex(
HANDLE pReportFile,
DWORD64 modBase,
DWORD dwTypeIndex,
unsigned nestingLevel,
DWORD_PTR offset);
/// <summary>
/// 输出类型的属性信息。
/// </summary>
/// <param name="pReportFile">
/// 异常报告输出的文件句柄。
/// </param>
/// <param name="modBase">
/// 模块基址。
/// </param>
/// <param name="dwTypeIndex">
/// 类型索引。
/// </param>
/// <param name="dwOffset">
/// 变量地址。
/// </param>
static void DumpTypeInfo(
HANDLE pReportFile,
DWORD64 modBase,
DWORD dwTypeIndex ,
DWORD_PTR dwOffset );
/// <summary>
/// 输出符号信息。
/// </summary>
/// <param name="pReportFile">
/// 异常报告输出的文件句柄。
/// </param>
/// <param name="pSymInfo">
/// 符号信息结构。
/// </param>
static void DumpSymbolInfo(
HANDLE pReportFile,
PSYMBOL_INFO pSymInfo );
/// <summary>
/// 获得基本类型的字符串描述。
/// </summary>
/// <param name="dwBasicType">
/// 基本类型。
/// </param>
/// <returns>
/// 基本类型的字符串表示。
/// </returns>
static WCHAR* GetBasicTypeString(
DWORD dwBasicType );
/// <summary>
/// 获得符号类型的字符串描述。
/// </summary>
/// <param name="dwSymbolTag">
/// 符号类型。
/// </param>
/// <returns>
/// 符号类型的字符串描述。
/// </returns>
static WCHAR* GetSymbolTagString(
DWORD dwSymbolTag );
/// <summary>
/// 格式化参数值。
/// </summary>
/// <param name="pReportFile">
/// 异常报告输出的文件句柄。
/// </param>
/// <param name="basicType">
/// 参数类型。
/// </param>
/// <param name="length">
/// 值长度。
/// </param>
/// <param name="pAddress">
/// 值地址。
/// </param>
static void FormatOutputValue(
HANDLE pReportFile,
DWORD basicType,
DWORD64 length,
PVOID pAddress );
/// <summary>
/// 格式化指针参数值。
/// </summary>
/// <param name="pReportFile">
/// 异常报告输出的文件句柄。
/// </param>
/// <param name="basicType">
/// 参数类型。
/// </param>
/// <param name="length">
/// 值长度。
/// </param>
/// <param name="pAddress">
/// 值地址。
/// </param>
static void FormatPointerValue(
HANDLE pReportFile,
DWORD basicType,
DWORD64 length,
PVOID pAddress );
/// <summary>
/// 输出可变类型的数据。
/// </summary>
/// <param name="pReportFile">
/// 异常报告输出的文件句柄。
/// </param>
/// <param name="pVal">
/// 待输出数值。
/// </param>
static void FormatVariantValue(
HANDLE pReportFile,
const VARIANT* pVal );
/// <summary>
/// 输出信息到文件。
/// </summary>
/// <param name="pReportFile">
/// 文件句柄。
/// </param>
/// <param name="format">
/// 格式化字符串。
/// </param>
/// <returns>
/// 写入的字符个数。
/// </returns>
static int __cdecl PrintOut(
HANDLE pReportFile,
const WCHAR * format, ...);
//==============================================================================
// 静态成员变量
//==============================================================================
/// 异常报告输出文件路径
static WCHAR m_szReportFileName[MAX_PATH];
/// 异常过滤函数指针
static LPTOP_LEVEL_EXCEPTION_FILTER m_previousFilter;
/// 异常报告输出文件句柄
static HANDLE m_hReportFile;
/// 进程句柄
static HANDLE m_hProcess;
// 并发控制(DBGHELP库不能被多个线程同时访问)
static CRITICAL_SECTION m_csDbgHelp;
};
//==============================================================================
#endif // __XDBEXCEPTIONREPORT__H__INCLUDED__
//==============================================================================
SEH转化为C++异常<二>
最新推荐文章于 2021-08-20 15:43:38 发布