Windows程序添加崩溃异常信息代码
#include <string>
#include <DbgHelp.h>
#include <tlhelp32.h>
#include <VersionHelpers.h>
class CCrashStack
{
private:
PEXCEPTION_POINTERS m_pException;
private:
std::wstring GetModuleByRetAddr(PBYTE Ret_Addr, PBYTE& Module_Addr)
{
MODULEENTRY32W M = { sizeof(M) };
HANDLE hSnapshot;
std::wstring wModuleName = L"";
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0);
if ((hSnapshot != INVALID_HANDLE_VALUE) &&
Module32FirstW(hSnapshot, &M))
{
do
{
if (DWORD(Ret_Addr - M.modBaseAddr) < M.modBaseSize)
{
wModuleName.assign(M.szExePath);
Module_Addr = M.modBaseAddr;
break;
}
} while (Module32NextW(hSnapshot, &M));
}
CloseHandle(hSnapshot);
return wModuleName;
}
std::wstring GetCallStack(PEXCEPTION_POINTERS pException)
{
PBYTE Module_Addr_1;
WCHAR bufer[MAX_PATH] = { 0 };
std::wstring sRet;
typedef struct STACK
{
STACK* Ebp;
PBYTE Ret_Addr;
DWORD Param[0];
} STACK, * PSTACK;
STACK Stack = { 0, 0 };
PSTACK Ebp;
if (pException) //fake frame for exception address
{
Stack.Ebp = (PSTACK)pException->ContextRecord->Ebp;
Stack.Ret_Addr = (PBYTE)pException->ExceptionRecord->ExceptionAddress;
Ebp = &Stack;
}
else
{
Ebp = (PSTACK)&pException - 1; //frame addr of Get_Call_Stack()
// Skip frame of Get_Call_Stack().
if (!IsBadReadPtr(Ebp, sizeof(PSTACK)))
{
Ebp = Ebp->Ebp; //caller ebp
}
}
// Break trace on wrong stack frame.
for (; !IsBadReadPtr(Ebp, sizeof(PSTACK)) && !IsBadCodePtr(FARPROC(Ebp->Ret_Addr)); Ebp = Ebp->Ebp)
{
// If module with Ebp->Ret_Addr found.
memset(bufer, 0, sizeof(bufer));
_swprintf(bufer, L"\n%08X ", (unsigned int)Ebp->Ret_Addr);
sRet.append(bufer);
std::wstring moduleName = this->GetModuleByRetAddr(Ebp->Ret_Addr, Module_Addr_1);
if (moduleName.empty() == false)
{
sRet.append(moduleName);
}
}
return sRet;
}
std::wstring GetVersionStr()
{
WCHAR wVer[512] = { 0 };
std::wstring winVer = L"";
if (IsWindowsXPOrGreater())
{
winVer = (L"XPOrGreater\n");
}
if (IsWindowsXPSP1OrGreater())
{
winVer = (L"XPSP1OrGreater\n");
}
if (IsWindowsXPSP2OrGreater())
{
winVer = (L"XPSP2OrGreater\n");
}
if (IsWindowsXPSP3OrGreater())
{
winVer = (L"XPSP3OrGreater\n");
}
if (IsWindowsVistaOrGreater())
{
winVer = (L"VistaOrGreater\n");
}
if (IsWindowsVistaSP1OrGreater())
{
winVer = (L"VistaSP1OrGreater\n");
}
if (IsWindowsVistaSP2OrGreater())
{
winVer = (L"VistaSP2OrGreater\n");
}
if (IsWindows7OrGreater())
{
winVer = (L"Windows7OrGreater\n");
}
if (IsWindows7SP1OrGreater())
{
winVer = (L"Windows7SP1OrGreater\n");
}
if (IsWindows8OrGreater())
{
winVer = (L"Windows8OrGreater\n");
}
if (IsWindows8Point1OrGreater())
{
winVer = (L"Windows8Point1OrGreater\n");
}
if (IsWindows10OrGreater())
{
winVer = (L"Windows10OrGreater\n");
}
if (IsWindowsServer())
{
winVer = (L"Server\n");
}
else
{
winVer = (L"Client\n");
}
_swprintf(wVer,
L"APP Version: v1.0\nWindows: %s\n", winVer.c_str());
return (wVer);
}
public:
CCrashStack(PEXCEPTION_POINTERS pException):m_pException(pException){}
std::wstring GetExceptionInfo()
{
WCHAR Module_Name[MAX_PATH];
PBYTE Module_Addr;
std::wstring sRet;
WCHAR buffer[512] = { 0 };
std::wstring sTmp = GetVersionStr();
sRet.append(sTmp);
sRet.append(L"Process: ");
GetModuleFileNameW(NULL, Module_Name, MAX_PATH);
sRet.append(Module_Name);
sRet.append(L"\n");
// If exception occurred.
if (m_pException)
{
EXCEPTION_RECORD& E = *m_pException->ExceptionRecord;
CONTEXT& C = *m_pException->ContextRecord;
memset(buffer, 0, sizeof(buffer));
_swprintf(buffer, L"Exception Addr: %08X ", (int)E.ExceptionAddress);
sRet.append(buffer);
// If module with E.ExceptionAddress found - save its path and date.
std::wstring module = GetModuleByRetAddr((PBYTE)E.ExceptionAddress, Module_Addr);
if (module.empty() == false)
{
sRet.append(L" Module: ");
sRet.append(module);
}
memset(buffer, 0, sizeof(buffer));
_swprintf(buffer, L"\nException Code: %08X\n", (int)E.ExceptionCode);
sRet.append(buffer);
if (E.ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
{
// Access violation type - Write/Read.
memset(buffer, 0, sizeof(buffer));
_swprintf(buffer, L"%s Address: %08X\n",
(E.ExceptionInformation[0]) ? L"Write" : L"Read", (int)E.ExceptionInformation[1]);
sRet.append(buffer);
}
sRet.append(L"Instruction: ");
for (int i = 0; i < 16; i++)
{
memset(buffer, 0, sizeof(buffer));
_swprintf(buffer, L" %02X", PBYTE(E.ExceptionAddress)[i]);
sRet.append(buffer);
}
sRet.append(L"\nRegisters: ");
memset(buffer, 0, sizeof(buffer));
_swprintf(buffer, L"\nEAX: %08X EBX: %08X ECX: %08X EDX: %08X", (unsigned int)C.Eax, (unsigned int)C.Ebx, (unsigned int)C.Ecx, (unsigned int)C.Edx);
sRet.append(buffer);
memset(buffer, 0, sizeof(buffer));
_swprintf(buffer, L"\nESI: %08X EDI: %08X ESP: %08X EBP: %08X", (unsigned int)C.Esi, (unsigned int)C.Edi, (unsigned int)C.Esp, (unsigned int)C.Ebp);
sRet.append(buffer);
memset(buffer, 0, sizeof(buffer));
_swprintf(buffer, L"\nEIP: %08X EFlags: %08X", (unsigned int)C.Eip, (unsigned int)C.EFlags);
sRet.append(buffer);
} //if (pException)
sRet.append(L"\nCall Stack:");
sRet.append(this->GetCallStack(m_pException));
return sRet;
}
public:
static long __stdcall callback(_EXCEPTION_POINTERS* excp)
{
CCrashStack crashStack(excp);
std::wstring sCrashInfo = crashStack.GetExceptionInfo();
FILE* pF = _wfopen(L"crash.log", L"w");
if (pF != nullptr)
{
fwprintf(pF, sCrashInfo.c_str());
fclose(pF);
}
return EXCEPTION_EXECUTE_HANDLER;
}
void CrashStackStart()
{
SetUnhandledExceptionFilter(callback);
}
};