加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

Qt--让你的客户端崩溃之前生成dump文件

发布时间:2020-12-13 21:14:16 所属栏目:PHP教程 来源:网络整理
导读:之前写过在windows开发中,让你的客户端崩溃之前生成dump文件,今天略微改动改动用在qt上吧。 windows客户端开发–让你的客户端崩溃之前生成dump文件 http://blog.csdn.net/wangshubo1989/article/details/51100612 定义1个类叫 CCrashStack : crashstack.h

之前写过在windows开发中,让你的客户端崩溃之前生成dump文件,今天略微改动改动用在qt上吧。

windows客户端开发–让你的客户端崩溃之前生成dump文件

http://blog.csdn.net/wangshubo1989/article/details/51100612

定义1个类叫CCrashStack
crashstack.h

#ifndef CCRASHSTACK_H #define CCRASHSTACK_H #include <windows.h> #include <QString> class CCrashStack { private: PEXCEPTION_POINTERS m_pException; private: QString GetModuleByRetAddr(PBYTE Ret_Addr,PBYTE & Module_Addr); QString GetCallStack(PEXCEPTION_POINTERS pException); QString GetVersionStr(); bool GetHardwareInaformation(QString &graphics_card,QString &sound_deivce); public: CCrashStack(PEXCEPTION_POINTERS pException); QString GetExceptionInfo(); }; #endif // CCRASHSTACK_H

crashstack.cc

#include "crashstack.h" #include <tlhelp32.h> #include <stdio.h> #define _WIN32_DCOM #include <comdef.h> #include <Wbemidl.h> #include<base/constants.h> #include "qdebug.h" CCrashStack::CCrashStack(PEXCEPTION_POINTERS pException) { m_pException = pException; } QString CCrashStack::GetModuleByRetAddr(PBYTE Ret_Addr,PBYTE & Module_Addr) { MODULEENTRY32 M = {sizeof(M)}; HANDLE hSnapshot; wchar_t Module_Name[MAX_PATH] = {0}; hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,0); if ((hSnapshot != INVALID_HANDLE_VALUE) && Module32First(hSnapshot,&M)) { do { if (DWORD(Ret_Addr - M.modBaseAddr) < M.modBaseSize) { lstrcpyn(Module_Name,M.szExePath,MAX_PATH); Module_Addr = M.modBaseAddr; break; } } while (Module32Next(hSnapshot,&M)); } CloseHandle(hSnapshot); QString sRet = QString::fromWCharArray(Module_Name); return sRet; } QString CCrashStack::GetCallStack(PEXCEPTION_POINTERS pException) { PBYTE Module_Addr_1; char bufer[256]={0}; QString 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(0)); sprintf(bufer,"n%08X ",(unsigned int)Ebp->Ret_Addr); sRet.append(bufer); QString moduleName = this->GetModuleByRetAddr(Ebp->Ret_Addr,Module_Addr_1) ; if (moduleName.length() > 0) { sRet.append(moduleName); } } return sRet; } //Get_Call_Stack QString CCrashStack::GetVersionStr() { OSVERSIONINFOEX V = {sizeof(OSVERSIONINFOEX)}; //EX for NT 5.0 and later if (!GetVersionEx((POSVERSIONINFO)&V)) { ZeroMemory(&V,sizeof(V)); V.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx((POSVERSIONINFO)&V); } if (V.dwPlatformId != VER_PLATFORM_WIN32_NT) V.dwBuildNumber = LOWORD(V.dwBuildNumber); //for 9x HIWORD(dwBuildNumber) = 0x04xx QString graphics_module = "GraphicsCard: "; QString sound_module = "SoundDevice: "; GetHardwareInaformation(graphics_module,sound_module); QString sRet = QString("APP Version: %1n").arg(APP_VERSION); sRet.append(QString("Windows: %1.%2.%3,SP %4.%5,Product Type %6n") .arg(V.dwMajorVersion).arg(V.dwMinorVersion).arg(V.dwBuildNumber) .arg(V.wServicePackMajor).arg(V.wServicePackMinor).arg(V.wProductType)); sRet.append(graphics_module); sRet.append(sound_module); return sRet; } QString CCrashStack::GetExceptionInfo() { WCHAR Module_Name[MAX_PATH]; PBYTE Module_Addr; QString sRet; char buffer[512]={0}; QString sTmp = GetVersionStr(); sRet.append(sTmp); sRet.append("Process: "); GetModuleFileName(NULL,Module_Name,MAX_PATH); sRet.append(QString::fromWCharArray(Module_Name)); sRet.append("n"); // If exception occurred. if (m_pException) { EXCEPTION_RECORD & E = *m_pException->ExceptionRecord; CONTEXT & C = *m_pException->ContextRecord; memset(buffer,sizeof(buffer)); sprintf(buffer,"Exception Addr: %08X ",(int)E.ExceptionAddress); sRet.append(buffer); // If module with E.ExceptionAddress found - save its path and date. QString module = GetModuleByRetAddr((PBYTE)E.ExceptionAddress,Module_Addr); if (module.length() > 0) { sRet.append(" Module: "); sRet.append(module); } memset(buffer,"nException Code: %08Xn",(int)E.ExceptionCode); sRet.append(buffer); if (E.ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { // Access violation type - Write/Read. memset(buffer,sizeof(buffer)); sprintf(buffer,"%s Address: %08Xn",(E.ExceptionInformation[0]) ? "Write" : "Read",(int)E.ExceptionInformation[1]); sRet.append(buffer); } sRet.append("Instruction: "); for (int i = 0; i < 16; i++) { memset(buffer," %02X",PBYTE(E.ExceptionAddress)[i]); sRet.append(buffer); } sRet.append("nRegisters: "); memset(buffer,"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,"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,"nEIP: %08X EFlags: %08X",(unsigned int)C.Eip,(unsigned int) C.EFlags); sRet.append(buffer); } //if (pException) sRet.append("nCall Stack:"); QString sCallstack = this->GetCallStack(m_pException); sRet.append(sCallstack); return sRet; } bool CCrashStack::GetHardwareInaformation(QString &graphics_card,QString &sound_deivce) { HRESULT hres; // Initialize COM. hres = CoInitializeEx(0,COINIT_APARTMENTTHREADED); if (FAILED(hres)) { qDebug() << "Failed to initialize COM library. " << "Error code = 0x" << hex << hres << endl; return false; } // Initialize hres = CoInitializeSecurity(NULL,-1,NULL,RPC_C_AUTHN_LEVEL_DEFAULT,RPC_C_IMP_LEVEL_IMPERSONATE,EOAC_NONE,NULL); if ((hres != RPC_E_TOO_LATE) && FAILED(hres)) { qDebug() << "Failed to initialize security. " << "Error code = 0x" << hex << hres << endl; CoUninitialize(); return false; } // Obtain the initial locator to Windows Management // on a particular host computer. IWbemLocator *pLoc = 0; hres = CoCreateInstance( CLSID_WbemLocator,CLSCTX_INPROC_SERVER,IID_IWbemLocator,(LPVOID *)&pLoc); if (FAILED(hres)) { qDebug() << "Failed to create IWbemLocator object. " << "Error code = 0x" << hex << hres << endl; CoUninitialize(); return false; } IWbemServices *pSvc = 0; // Connect to the rootcimv2 namespace with the // current user and obtain pointer pSvc // to make IWbemServices calls. hres = pLoc->ConnectServer(_bstr_t(L"ROOTCIMV2"),&pSvc); if (FAILED(hres)) { qDebug() << "Could not connect. Error code = 0x" << hex << hres << endl; pLoc->Release(); CoUninitialize(); return false; } // Set the IWbemServices proxy so that impersonation // of the user (client) occurs. hres = CoSetProxyBlanket( pSvc,// the proxy to set RPC_C_AUTHN_WINNT,// authentication service RPC_C_AUTHZ_NONE,// authorization service NULL,// Server principal name RPC_C_AUTHN_LEVEL_CALL,// authentication level RPC_C_IMP_LEVEL_IMPERSONATE,// impersonation level NULL,// client identity EOAC_NONE // proxy capabilities ); if (FAILED(hres)) { qDebug() << "Could not set proxy blanket. Error code = 0x" << hex << hres << endl; pSvc->Release(); pLoc->Release(); CoUninitialize(); return false; } // Use the IWbemServices pointer to make requests of WMI. // Make requests here: IEnumWbemClassObject* pEnumerator_graphics = NULL; IEnumWbemClassObject* pEnumerator_sound = NULL; BSTR wql = SysAllocString(L"WQL"); BSTR sql_graphics = SysAllocString(L"SELECT * FROM Win32_VideoController"); BSTR sql_sound = SysAllocString(L"SELECT * FROM Win32_SoundDevice"); HRESULT hres_graphics; HRESULT hres_sound; hres_graphics = pSvc->ExecQuery(wql,sql_graphics,WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,&pEnumerator_graphics); hres_sound = pSvc->ExecQuery(wql,sql_sound,&pEnumerator_sound); if (FAILED(hres_graphics) || FAILED(hres_sound)) { qDebug() << "Query for processes failed. " << "Error code = 0x" << hex << hres_graphics << endl; qDebug() << "Query for processes failed. " << "Error code = 0x" << hex << hres_sound << endl; pSvc->Release(); pLoc->Release(); CoUninitialize(); return ""; } else { IWbemClassObject *pclsObj_graphics; ULONG uReturnGraphics = 0; IWbemClassObject *pclsObj_sound; ULONG uReturnSound = 0; while (pEnumerator_graphics) { hres_graphics = pEnumerator_graphics->Next(WBEM_INFINITE,1,&pclsObj_graphics,&uReturnGraphics); if (0 == uReturnGraphics) { break; } VARIANT description_vtProp; VARIANT driver_version_vtProp; VARIANT status_vtProp; // Get the value of the Name property hres_graphics = pclsObj_graphics->Get(L"Description",&description_vtProp,0); QString description((QChar*) description_vtProp.bstrVal,wcslen(description_vtProp.bstrVal)); hres_graphics = pclsObj_graphics->Get(L"DriverVersion",&driver_version_vtProp,0); QString driver_version((QChar*) driver_version_vtProp.bstrVal,wcslen(driver_version_vtProp.bstrVal)); hres_graphics = pclsObj_graphics->Get(L"Status",&status_vtProp,0); QString status((QChar*) status_vtProp.bstrVal,wcslen(status_vtProp.bstrVal)); graphics_card.append(description).append(" ").append(driver_version).append(" ").append(status).append(" n"); VariantClear(&description_vtProp); VariantClear(&driver_version_vtProp); VariantClear(&status_vtProp); } while (pEnumerator_sound) { hres_sound = pEnumerator_sound->Next(WBEM_INFINITE,&pclsObj_sound,&uReturnSound); if (0 == uReturnSound) { break; } VARIANT description_vtProp; VARIANT status_vtProp; // Get the value of the Name property hres_sound = pclsObj_sound->Get(L"Description",wcslen(description_vtProp.bstrVal)); hres_sound = pclsObj_sound->Get(L"Status",wcslen(status_vtProp.bstrVal)); sound_deivce.append(description).append(" ").append(status).append(" n"); VariantClear(&description_vtProp); VariantClear(&status_vtProp); } } // Cleanup pSvc->Release(); pLoc->Release(); CoUninitialize(); return true; }

上面的代码有些啰嗦,同时记录了1些硬件的信息到dump文件中(http://blog.csdn.net/wangshubo1989/article/details/51855895);
如果感觉没用,请自行疏忽。

开始使用:
在main.cc文件中:

首先定义1下回调:

#ifdef Q_OS_WIN long __stdcall callback(_EXCEPTION_POINTERS* excp) { CCrashStack crashStack(excp); QString sCrashInfo = crashStack.GetExceptionInfo(); TCHAR my_documents[MAX_PATH]; SHGetFolderPath(NULL,CSIDL_PERSONAL,SHGFP_TYPE_CURRENT,my_documents); QString file_path = QString::fromWCharArray(my_documents); QDir *folder_path = new QDir; bool exist = folder_path->exists(file_path.append("MyApp")); if(!exist) { folder_path->mkdir(file_path); } delete folder_path; folder_path = nullptr; QString sFileName = file_path + "crash.log"; QFile file(sFileName); if (file.open(QIODevice::WriteOnly|QIODevice::Truncate)) { file.write(sCrashInfo.toUtf8()); file.close(); } return EXCEPTION_EXECUTE_HANDLER; } #endif

最后再main中添加:

#ifdef Q_OS_WIN SetUnhandledExceptionFilter(callback); #endif

关于SetUnhandledExceptionFilter不懂的地方可以参考:
http://blog.csdn.net/wangshubo1989/article/details/51100612

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读