⑴ 如何手工抓取mp文件
通常在CDialog::OnInitDialog中調用,用於將對話框定位到應用程序主窗口的中央。在預設情況下,這個函數將子窗口定位到它們的父窗口的中央,而將彈出窗口定位到擁有者的中央。如果彈出窗口沒有擁有者,它將被定位到屏幕中央。如果要使窗口根據不是父窗口也不是擁有者的窗口來定位,則可以將pAlternateOwner參數可以被設為一個有效的窗口。如果要強迫相對於屏幕定位,則應在pAlternateOwner參數中傳遞CWnd::GetDesktopWindow返回的值。
⑵ 如何讓程序抓到mp文件,MiniDumpWriteDump
程序崩潰(crash)的時候, 為了以後能夠調試分析問題, 可以使用WinDBG要把當時程序內存空間數據都保存下來,生成的文件稱為mp 文件。
步驟:
1) 打開WinDBG並將之Attach 到crash的程序進程
2) 輸入產生mp 文件的命令
WinDBG產生mp 文件的命令是 .mp ,可以選擇不同的參數來生成不同類型的mp文件。
選項(1): /m
命令行示例:.mp /m C:\mps\myapp.dmp
註解: 預設選項,生成標準的minimp, 轉儲文件通常較小,便於在網路上通過郵件或其他方式傳輸。 這種文件的信息量較少,只包含系統信息、載入的模塊(DLL)信息、 進程信息和線程信息。
選項(2): /ma
命令行示例:.mp /ma C:\mps\myapp.dmp
註解: 帶有盡量多選項的minimp(包括完整的內存內容、句柄、未載入的模塊,等等),文件很大,但如果條件允許(本機調試,區域網環境), 推薦使用這中mp。
選項(3):/mFhutwd
命令行示例:.mp /mFhutwd C:\mps\myapp.dmp
註解:帶有數據段、非共享的讀/寫內存頁和其他有用的信息的minimp。包含了通過minimp能夠得到的最多的信息。是一種折中方案。
上面介紹如如何用WinDBG 生成crash mp 《WinDBG 技巧:如何生成Dump 文件(.mp 命令) 》,但是用戶機器上通常不安裝WinDBG, 而且多數用戶也不知道怎麼使用WinDBG。 所以最好是自己程序裡面能夠捕捉exception/crash,並且生成crash mp,然後通過網路傳回到自己伺服器。
捕捉exception 可以用API 函數 SetUnhandledExceptionFilter 。
生成crash mp 可以用DbgHelp.dll 裡面的MiniDumpWriteDump 函數。
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilter( __in LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter );
BOOL WINAPI MiniDumpWriteDump( __in HANDLE hProcess, __in Dword ProcessId, __in HANDLE hFile, __in MINIDUMP_TYPE DumpType, __in PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, __in PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, __in PMINIDUMP_CALLBACK_INFORMATION CallbackParam );
【代碼實例】
#include <dbghelp.h>
#include <shellapi.h>
#include <shlobj.h>
// 自定義的exectpion filter
LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS*pExceptionPointers)
{
SetErrorMode( SEM_NOGPFAULTERRORBOX );
//收集信息
CStringW strBuild;
strBuild.Format(L"Build: %s %s", __DATE__, __TIME__);
CStringW strError;
HMODULE hMole;
WCHAR szMoleName[MAX_PATH] = L"";
GetMoleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,(LPCWSTR)pExceptionPointers->ExceptionRecord->ExceptionAddress,&hMole);
GetMoleFileName(hMole, szMoleName, ARRAYSIZE(szMoleName));
strError.AppenedFormat(L"%s %d , %d ,%d.",szMoleName,pExceptionPointers->ExceptionRecord->ExceptionCode,pExceptionPointers->ExceptionRecord->ExceptionFlags,pExceptionPointers->ExceptionRecord->ExceptionAddress);
//生成 mini crash mp
BOOL bMiniDumpSuccessful;
WCHAR szPath[MAX_PATH];
WCHAR szFileName[MAX_PATH];
WCHAR* szAppName = L"AppName";
WCHAR* szVersion = L"v1.0";
DWORD dwBufferSize = MAX_PATH;
HANDLE hDumpFile;
SYSTEMTIME stLocalTime;
MINIDUMP_EXCEPTION_INFORMATION ExpParam;
GetLocalTime( &stLocalTime );
GetTempPath( dwBufferSize, szPath );
StringCchPrintf( szFileName, MAX_PATH, L"%s%s", szPath, szAppName);
CreateDirectory( szFileName, NULL );
StringCchPrintf( szFileName, MAX_PATH, L"%s%s\\%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp",
szPath, szAppName, szVersion,
stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
stLocalTime.wHour, stLocalTime.wMinute,stLocalTime.wSecond,
GetCurrentProcessId(), GetCurrentThreadId());
hDumpFile = CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0,0);
MINIDUMP_USER_STREAM UserStream[2];
MINIDUMP_USER_STREAM_INFORMATION UserInfo;
UserInfo.UserStreamCount = 1;
UserInfo.UserStreamArray = UserStream;
UserStream[0].Type = CommentStreamW;
UserStream[0].BufferSize = strBuild.GetLength()*sizeof(WCHAR);
UserStream[0].Buffer = strBuild.GetBuffer();
UserStream[1].Type = CommentStreamW;
UserStream[1].BufferSize = strError.GetLength()*sizeof(WCHAR);
UserStream[1].Buffer = strError.GetBuffer();
ExpParam.ThreadId = GetCurrentThreadId();
ExpParam.ExceptionPointers = pExceptionPointers;
ExpParam.ClientPointers = TRUE;
MINIDUMP_TYPE MiniDumpWithDataSegs = MiniDumpNormal
| MiniDumpWithHandleData
| MiniDumpWithUnloadedMoles
|
| MiniDumpScanMemory
| MiniDumpWithProcessThreadData
| MiniDumpWithThreadInfo;
bMiniDumpSuccessful = MiniDumpWriteDump(GetCurrentProcess(),GetCurrentProcessId(),
hDumpFile, MiniDumpWithDataSegs, &ExpParam, NULL,NULL);
// 上傳mini mp 到自己伺服器(略)
...
return EXCEPTION_CONTINUE_SEARCH; //或者 EXCEPTION_EXECUTE_HANDLER 關閉程序
}
int _tmain()
{
// 設置 execption filter
SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
....
return 0;
}
正常情況下不會生成mp,需要自己在程序中添加代碼實現,一般是利用MS的dbghelp.dll提供的DbgHelpCreateUserDump來生成,用WinDbg來分析,期間需要編譯程序生成的.pdb文件。可以參考BlackBox、google breakpad等
crash 文件生成的路徑:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug]
"Auto"="0"
"Debugger"="\"D:\\WinDBG\\ntsd.exe\" -p %ld -e %ld -g -noio -c \".mp /ma /u d:\\dbgdmp\\dmp.dmp; q"
"UserDebuggerHotKey"=dword:00000000
⑶ 電腦藍屏後如何找到mp文件
直觀地說,藍屏是系統崩潰。操作系統在遇到致命錯誤導致崩潰時,並不是直接掛掉,而是會記錄下當時內存中的數據,將其存儲成為mp文件,並用一串藍屏代碼向用戶做出提示。
第一步,打開電腦的mp文件存儲功能。在「我的電腦」上右鍵——屬性——高級,選好後點確定,下次再出現藍屏時,系統就會存儲下mp文件,一般存放位置在系統盤的minimp文件夾下。(建議在該文件夾上點右鍵——屬性——發送到——桌面快捷方式,以後就能在桌面上找到該文件夾了)
第二步,下載安裝windbghttp://www.microsoft.com/whdc/devtools/debugging/installx86.mspx#a
這個過程就不說了,隨便選一個下載,安裝時,一路「下一步」就行了。
第三步,使用windbg診斷藍屏錯誤
上面兩步設好後,就想辦法開始「製造」藍屏吧,平時怎麼用會出現藍屏就拚命用直到出現藍屏.
藍屏後重啟,在minimp文件夾下會出現一個以日期為文件名的東東,那就是我們要的了。接下來打開windbg,點屏幕左下的 「開始」,軟體啟動點File——Open Crash Dump, 然後找到minimp文件夾,mp文件一般是"時間.dmp",打開後就會自動分析了。分析完後,看最下面,找到3.probably caused by這一行, 那個myfault.sys文件就是罪魁禍首。 導入mp文件分析完畢後,不要關閉,在後面輸入 !analyze -v ,這個命令可以查看mp文件的詳細情況