Windows程序添加崩溃异常信息代码

xingyun86 2022-2-16 1304

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);
	}
};


×
打赏作者
最新回复 (0)
查看全部
全部楼主
返回