vc6.0 mfc 生成 dump
// vc6mfcdumptest.cpp : Defines the entry point for the console application.
//
#define DNC_MINIDUMP
#include "stdafx.h"
#include "vc6mfcdumptest.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// The one and only application object
CWinApp theApp;
using namespace std;
#ifdef DNC_MINIDUMP
LONG WINAPI DNCUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *pExceptionPointers)
{
TCHAR szProgramPath[MAX_PATH] = {0};
if(GetModuleFileName(NULL, szProgramPath, MAX_PATH))
{
LPTSTR lpSlash = _tcsrchr(szProgramPath, '\\');
if(lpSlash)
{
*(lpSlash + 1) = '\0';
}
}
time_t t = time(0);
char tmp[64];
strftime( tmp, sizeof(tmp), "%Y%m%d-%H%M",localtime(&t) );
TCHAR szDumpFile[MAX_PATH] = {0};
_stprintf(szDumpFile, _T("%s%s.dmp"), szProgramPath, tmp);
HANDLE hDumpFile = CreateFile(szDumpFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL ,NULL);
MINIDUMP_EXCEPTION_INFORMATION stMiniDumpExceptionInfo;
stMiniDumpExceptionInfo.ExceptionPointers = pExceptionPointers;
stMiniDumpExceptionInfo.ThreadId = GetCurrentThreadId();
stMiniDumpExceptionInfo.ClientPointers = TRUE;
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile,
MiniDumpNormal, &stMiniDumpExceptionInfo, NULL, NULL);
CloseHandle(hDumpFile);
return EXCEPTION_EXECUTE_HANDLER;
}
#endif
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
#ifdef DNC_MINIDUMP
SetUnhandledExceptionFilter(DNCUnhandledExceptionFilter);
#endif
// 使程序崩溃产生 Dump 文件
int* p = NULL;
*p = 1;
}
return nRetCode;
}
vc++ 生成 dump
#include <iostream>
#include <tchar.h>
#include "Windows.h"
#include "DbgHelp.h"
#pragma comment(lib,"dbghelp.lib")
int GenerateMiniDump(PEXCEPTION_POINTERS pExceptionPointers)
{
// 定义函数指针
typedef BOOL(WINAPI* MiniDumpWriteDumpT)(
HANDLE,
DWORD,
HANDLE,
MINIDUMP_TYPE,
PMINIDUMP_EXCEPTION_INFORMATION,
PMINIDUMP_USER_STREAM_INFORMATION,
PMINIDUMP_CALLBACK_INFORMATION
);
// 从 "DbgHelp.dll" 库中获取 "MiniDumpWriteDump" 函数
MiniDumpWriteDumpT pfnMiniDumpWriteDump = NULL;
HMODULE hDbgHelp = LoadLibrary(_T("DbgHelp.dll"));
if (NULL == hDbgHelp)
{
return EXCEPTION_CONTINUE_EXECUTION;
}
pfnMiniDumpWriteDump = (MiniDumpWriteDumpT)GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
if (NULL == pfnMiniDumpWriteDump)
{
FreeLibrary(hDbgHelp);
return EXCEPTION_CONTINUE_EXECUTION;
}
// 创建 dmp 文件件
TCHAR szFileName[MAX_PATH] = { 0 };
TCHAR temp[] = _T("DumpDemo_v1.0");
TCHAR* szVersion = temp;
SYSTEMTIME stLocalTime;
GetLocalTime(&stLocalTime);
wsprintf(szFileName, L"%s-%04d%02d%02d-%02d%02d%02d.dmp",
szVersion, stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond);
HANDLE hDumpFile = CreateFile(szFileName, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
if (INVALID_HANDLE_VALUE == hDumpFile)
{
FreeLibrary(hDbgHelp);
return EXCEPTION_CONTINUE_EXECUTION;
}
// 写入 dmp 文件
MINIDUMP_EXCEPTION_INFORMATION expParam;
expParam.ThreadId = GetCurrentThreadId();
expParam.ExceptionPointers = pExceptionPointers;
expParam.ClientPointers = FALSE;
pfnMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
hDumpFile, MiniDumpWithDataSegs, (pExceptionPointers ? &expParam : NULL), NULL, NULL);
// 释放文件
CloseHandle(hDumpFile);
FreeLibrary(hDbgHelp);
return EXCEPTION_EXECUTE_HANDLER;
}
LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS lpExceptionInfo)
{
// 这里做一些异常的过滤或提示
if (IsDebuggerPresent())
{
return EXCEPTION_CONTINUE_SEARCH;
}
return GenerateMiniDump(lpExceptionInfo);
}
int main()
{
// 加入崩溃dump文件功能
SetUnhandledExceptionFilter(ExceptionFilter);
// 使程序崩溃产生 Dump 文件
int* p = NULL;
*p = 1;
}
参考:
visual studio 下 C++生成dump文件_vc++ minidumpwritedump-CSDN博客
c# 生成 .dmp
生成方式1:DumpHelper.cs 帮助类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace NetDumpTest
{
public class DumpHelper
{
[Flags]
public enum DumpType : uint
{
// From dbghelp.h:
MiniDumpNormal = 0x00000000, //只包含调用栈相关信息
MiniDumpWithDataSegs = 0x00000001, //包含已加载的模块的数据段信息,比如全局变量
MiniDumpWithFullMemory = 0x00000002, //包含全部可访问的内存
MiniDumpWithHandleData = 0x00000004, //包含句柄信息
MiniDumpFilterMemory = 0x00000008, //过滤一些敏感信息,保护重建调用栈需要的信息
MiniDumpScanMemory = 0x00000010, //扫描,以包含引用内存
MiniDumpWithUnloadedModules = 0x00000020, //包含最近被卸载的模块信息
MiniDumpWithIndirectlyReferencedMemory = 0x00000040,//包含未直接引用的内存
MiniDumpFilterModulePaths = 0x00000080, //过滤某块的路径信息
MiniDumpWithProcessThreadData = 0x00000100, //包含完整的进程和线程信息
MiniDumpWithPrivateReadWriteMemory = 0x00000200, //包含页面属性为 PAGE_READWRITE 的页面
MiniDumpWithoutOptionalData = 0x00000400, //不包含可选数据
MiniDumpWithFullMemoryInfo = 0x00000800, //包含内存区信息
MiniDumpWithThreadInfo = 0x00001000, //包含线程状态信息
MiniDumpWithCodeSegs = 0x00002000, //包含所有代码和有关的内存段
MiniDumpWithoutAuxiliaryState = 0x00004000, //关闭辅助内存收集
MiniDumpWithFullAuxiliaryState = 0x00008000, //使用所有的内存收集器
MiniDumpWithPrivateWriteCopyMemory = 0x00010000, //包含页面属性为 PAGE_WRITECOPY 的页面
MiniDumpIgnoreInaccessibleMemory = 0x00020000, //忽略不可访问的页面
MiniDumpValidTypeFlags = 0x0003ffff, //包含安全令牌相关信息
};
//typedef struct _MINIDUMP_EXCEPTION_INFORMATION {
// DWORD ThreadId;
// PEXCEPTION_POINTERS ExceptionPointers;
// BOOL ClientPointers;
//} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION;
[StructLayout(LayoutKind.Sequential, Pack = 4)] // Pack=4 is important! So it works also for x64!
struct MiniDumpExceptionInformation
{
public uint ThreadId;
public IntPtr ExceptioonPointers;
[MarshalAs(UnmanagedType.Bool)]
public bool ClientPointers;
}
//BOOL
//WINAPI
//MiniDumpWriteDump(
// __in HANDLE hProcess, :要转储的进程句柄。
// __in DWORD ProcessId, :要转储的进程ID。
// __in HANDLE hFile, :通过 CreateFile() 等 API 打开的,用来保存 dump 的文件句柄。
// __in MINIDUMP_TYPE DumpType, :转储类型。此参数会直接影响转储文件的大小
// __in_opt PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, :指向异常信息结构 MiniDumpExceptionInformation 的指针。如果本参数为 NULL,则转储文件中不会包含异常信息。
// __in_opt PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, :指向用户自定义信息结构的指针
// __in_opt PMINIDUMP_CALLBACK_INFORMATION CallbackParam :指向回调例程 MINIDUMP_CALLBACK_INFORMATION 的指针。如果此参数为NULL,转储过程中不会执行任何回调例程。
// );
[DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
static extern bool MiniDumpWriteDump(
IntPtr hProcess,
uint processId,
IntPtr hFile,
uint dumpType,
ref MiniDumpExceptionInformation expParam,
IntPtr userStreamParam,
IntPtr callbackParam);
[DllImport("kernel32.dll", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)]
static extern uint GetCurrentThreadId();
[DllImport("kernel32.dll", EntryPoint = "GetCurrentProcess", ExactSpelling = true)]
static extern IntPtr GetCurrentProcess();
[DllImport("kernel32.dll", EntryPoint = "GetCurrentProcessId", ExactSpelling = true)]
static extern uint GetCurrentProcessId();
public static bool WriteDump(string fileName)
{
return Write(fileName, DumpType.MiniDumpNormal);
}
public static bool Write(string fileName, DumpType dumpType)
{
var path = Path.Combine(Environment.CurrentDirectory, fileName);
using var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
MiniDumpExceptionInformation exp;
exp.ThreadId = GetCurrentThreadId();
exp.ClientPointers = false;
exp.ExceptioonPointers = Marshal.GetExceptionPointers();
bool bRet = MiniDumpWriteDump(
GetCurrentProcess(),
GetCurrentProcessId(),
fs.SafeFileHandle.DangerousGetHandle(),
(uint)dumpType,
ref exp,
IntPtr.Zero,
IntPtr.Zero);
return bRet;
}
}
}
生成方式2:MiniDump.cs 帮助类
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace NetDumpTest
{
public class MiniDump
{
public static void AutoGenerateDumpWhenCrash()
{
//参考文档:https://docs.microsoft.com/en-us/windows/win32/wer/collecting-user-mode-dumps?redirectedfrom=MSDN
//注册表里,添加【程序崩溃后,自动生成dump文件配置】
//注册表需要admin权限!
try
{
var outputDmpPath = AppDomain.CurrentDomain.BaseDirectory + "Dump";
if (!Directory.Exists(outputDmpPath))
{
Directory.CreateDirectory(outputDmpPath);
}
var fileName = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
var processName = fileName.Substring(fileName.LastIndexOf('\\') + 1);
//注册表地址
string regPath = @"SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\" + processName;
var reg = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);//Registry64防止注册表重定向到wow64
var subKey = reg.CreateSubKey(regPath);
subKey.SetValue("DumpCount", 1, RegistryValueKind.DWord);//dump文件个数
subKey.SetValue("DumpFolder", outputDmpPath, RegistryValueKind.ExpandString);//dump文件目录
subKey.SetValue("DumpType", 1, RegistryValueKind.DWord);//dump文件类型
}
catch (Exception ex)
{
//CLoggerTools.Warning2File(CLoggerFileName.strException, "{0},{1},{2}", "UI.Program", ex.Message, ex.StackTrace.Replace("\r\n", ""));
return;
}
}
// Taken almost verbatim from http://blog.kalmbach-software.de/2008/12/13/writing-minidumps-in-c/
[Flags]
public enum Option : uint
{
// From dbghelp.h:
Normal = 0x00000000,
WithDataSegs = 0x00000001,
WithFullMemory = 0x00000002,
WithHandleData = 0x00000004,
FilterMemory = 0x00000008,
ScanMemory = 0x00000010,
WithUnloadedModules = 0x00000020,
WithIndirectlyReferencedMemory = 0x00000040,
FilterModulePaths = 0x00000080,
WithProcessThreadData = 0x00000100,
WithPrivateReadWriteMemory = 0x00000200,
WithoutOptionalData = 0x00000400,
WithFullMemoryInfo = 0x00000800,
WithThreadInfo = 0x00001000,
WithCodeSegs = 0x00002000,
WithoutAuxiliaryState = 0x00004000,
WithFullAuxiliaryState = 0x00008000,
WithPrivateWriteCopyMemory = 0x00010000,
IgnoreInaccessibleMemory = 0x00020000,
ValidTypeFlags = 0x0003ffff,
}
enum ExceptionInfo
{
None,
Present
}
//typedef struct _MINIDUMP_EXCEPTION_INFORMATION {
// DWORD ThreadId;
// PEXCEPTION_POINTERS ExceptionPointers;
// BOOL ClientPointers;
//} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION;
[StructLayout(LayoutKind.Sequential, Pack = 4)] // Pack=4 is important! So it works also for x64!
struct MiniDumpExceptionInformation
{
public uint ThreadId;
public IntPtr ExceptionPointers;
[MarshalAs(UnmanagedType.Bool)]
public bool ClientPointers;
}
//BOOL
//WINAPI
//MiniDumpWriteDump(
// __in HANDLE hProcess,
// __in DWORD ProcessId,
// __in HANDLE hFile,
// __in MINIDUMP_TYPE DumpType,
// __in_opt PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
// __in_opt PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
// __in_opt PMINIDUMP_CALLBACK_INFORMATION CallbackParam
// );
// Overload requiring MiniDumpExceptionInformation
[DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, ref MiniDumpExceptionInformation expParam, IntPtr userStreamParam, IntPtr callbackParam);
// Overload supporting MiniDumpExceptionInformation == NULL
[DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, IntPtr expParam, IntPtr userStreamParam, IntPtr callbackParam);
[DllImport("kernel32.dll", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)]
static extern uint GetCurrentThreadId();
static bool Write(SafeHandle fileHandle, Option options, ExceptionInfo exceptionInfo)
{
Process currentProcess = Process.GetCurrentProcess();
IntPtr currentProcessHandle = currentProcess.Handle;
uint currentProcessId = (uint)currentProcess.Id;
MiniDumpExceptionInformation exp;
exp.ThreadId = GetCurrentThreadId();
exp.ClientPointers = false;
exp.ExceptionPointers = IntPtr.Zero;
if (exceptionInfo == ExceptionInfo.Present)
{
exp.ExceptionPointers = Marshal.GetExceptionPointers();
}
return exp.ExceptionPointers == IntPtr.Zero ? MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint)options, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero) : MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint)options, ref exp, IntPtr.Zero, IntPtr.Zero);
}
static bool Write(SafeHandle fileHandle, Option dumpType)
{
return Write(fileHandle, dumpType, ExceptionInfo.None);
}
public static Boolean TryDump(String dmpPath, Option dmpType = Option.Normal)
{
var path = Path.Combine(Environment.CurrentDirectory, dmpPath);
var dir = Path.GetDirectoryName(path);
if (dir != null && !Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
using (var fs = new FileStream(path, FileMode.Create))
{
return Write(fs.SafeFileHandle, dmpType);
}
}
}
}
生成.dmp
namespace NetDumpTest
{
internal class Program
{
static void Main(string[] args)
{
//生成方式1
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(
(obj, args) => DumpHelper.WriteDump($"Error_{DateTime.Now.ToString("yyyy_M_dd_HH_mm")}.dmp")
);
//生成方式2
MiniDump.AutoGenerateDumpWhenCrash();
int[] a = { 1,2};
a[10] = 10; //异常
}
}
}
参考:
.NET -- 使用Dump文件分析异常_c# dump-CSDN博客
vs 调试 debug
- vs 打开 .dmp文件
- 配置源码位置
C:\Users\32763\Desktop\workspace\cpp\DumpTest\DumpTest
- 本机调试
- 定位异常
c++
c#
备注: c# 调试时,需要完整加载 miscrosoft 符号,否则无法加载至源码:
参考:
使用VS调试Dump文件-CSDN博客使用VS调试Dump文件-CSDN博客
windbg 调试 dmp
- windbg 操作页面介绍
Windbg调试(使用方法)_windbg怎么用-CSDN博客
- 配置路径
- Open Crash Dump... : .dmp文件
- Symbol File Path ... : 符号文件.pdb
- Source File Path ... : 源代码
- 常用指令
!analyze -v # 查看数据
~*kbn # 查看所有线程
参考:
- .dmp文件调试参考:
windbg使用超详细教程(我是新手,大佬轻虐) - 知乎 (zhihu.com)
- 附加进程调试参考: