如何实现与Windows任务管理器效果一致的进程转储功能?
实现与Windows任务管理器一致的进程转储功能
你遇到的核心问题是转储类型的选择:你的代码使用了MiniDumpNormal,这是最小的转储类型,仅包含线程栈、模块列表等基础信息,所以体积只有300KB;而Windows任务管理器默认生成的是完整用户模式转储,包含进程的所有用户态内存、句柄信息、已卸载模块等数据,因此体积达到200MB左右。
解决方法:修改转储类型参数
将MiniDumpWriteDump的第四个参数替换为更全面的转储类型组合,以下是接近任务管理器行为的配置:
MiniDumpWithFullMemory | MiniDumpWithHandleData | MiniDumpWithUnloadedModules | MiniDumpWithProcessThreadData
各参数的作用:
MiniDumpWithFullMemory:包含进程的所有用户态内存(这是体积增大的主要原因)MiniDumpWithHandleData:包含进程持有的所有句柄信息MiniDumpWithUnloadedModules:包含已从进程中卸载的模块信息MiniDumpWithProcessThreadData:包含进程和线程的详细属性信息
同时,调整OpenProcess的权限,不需要过度使用PROCESS_ALL_ACCESS(容易因权限不足失败),改用所需的最小权限组合:
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_DUP_HANDLE
修改后的完整C++代码
#include <windows.h> #include <dbghelp.h> #include <stdio.h> #pragma comment(lib, "dbghelp.lib") void CreateFullDump(DWORD processId) { // 打开目标进程,使用最小必要权限 HANDLE processHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_DUP_HANDLE, FALSE, processId); if (processHandle == NULL) { printf("打开进程失败,错误码: %u\n", GetLastError()); return; } // 生成转储文件名 char dumpFileName[MAX_PATH]; sprintf_s(dumpFileName, sizeof(dumpFileName), "FullDump_%u.dmp", processId); // 创建转储文件 HANDLE dumpFile = CreateFileA(dumpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (dumpFile == INVALID_HANDLE_VALUE) { printf("创建转储文件失败,错误码: %u\n", GetLastError()); CloseHandle(processHandle); return; } // 写入完整转储(无异常场景,传入NULL作为异常信息) BOOL success = MiniDumpWriteDump( processHandle, processId, dumpFile, MiniDumpWithFullMemory | MiniDumpWithHandleData | MiniDumpWithUnloadedModules | MiniDumpWithProcessThreadData, NULL, // 正常转储无需异常信息 NULL, NULL ); if (!success) { printf("写入转储失败,错误码: %u\n", GetLastError()); } else { printf("转储创建成功: %s\n", dumpFileName); } // 清理资源 CloseHandle(dumpFile); CloseHandle(processHandle); } int main() { DWORD targetProcessId = 13940; // 替换为目标进程ID CreateFullDump(targetProcessId); return 0; }
C# 实现思路
通过P/Invoke调用DbgHelp.dll的MiniDumpWriteDump方法,同样设置上述转储类型:
using System; using System.Runtime.InteropServices; using System.IO; public class DumpCreator { [DllImport("dbghelp.dll", SetLastError = true)] private static extern bool MiniDumpWriteDump( IntPtr hProcess, uint processId, IntPtr hFile, uint dumpType, IntPtr exceptionParam, IntPtr userStreamParam, IntPtr callbackParam); [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId); [DllImport("kernel32.dll", SetLastError = true)] private static extern bool CloseHandle(IntPtr hObject); private const uint PROCESS_QUERY_INFORMATION = 0x0400; private const uint PROCESS_VM_READ = 0x0010; private const uint PROCESS_DUP_HANDLE = 0x0040; private const uint MiniDumpWithFullMemory = 0x00000002; private const uint MiniDumpWithHandleData = 0x00000040; private const uint MiniDumpWithUnloadedModules = 0x00000200; private const uint MiniDumpWithProcessThreadData = 0x00000008; public static void CreateFullDump(uint processId, string dumpPath) { IntPtr processHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_DUP_HANDLE, false, processId); if (processHandle == IntPtr.Zero) { throw new System.ComponentModel.Win32Exception(); } using (FileStream fs = new FileStream(dumpPath, FileMode.Create)) { bool success = MiniDumpWriteDump( processHandle, processId, fs.SafeFileHandle.DangerousGetHandle(), MiniDumpWithFullMemory | MiniDumpWithHandleData | MiniDumpWithUnloadedModules | MiniDumpWithProcessThreadData, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); if (!success) { throw new System.ComponentModel.Win32Exception(); } } CloseHandle(processHandle); } static void Main() { uint targetProcessId = 13940; CreateFullDump(targetProcessId, $"FullDump_{targetProcessId}.dmp"); } }
Python 实现思路
使用ctypes调用Windows API,同样配置正确的转储类型:
import ctypes from ctypes import wintypes # 定义常量 PROCESS_QUERY_INFORMATION = 0x0400 PROCESS_VM_READ = 0x0010 PROCESS_DUP_HANDLE = 0x0040 MiniDumpWithFullMemory = 0x00000002 MiniDumpWithHandleData = 0x00000040 MiniDumpWithUnloadedModules = 0x00000200 MiniDumpWithProcessThreadData = 0x00000008 # 加载DLL kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) dbghelp = ctypes.WinDLL('dbghelp', use_last_error=True) # 定义函数原型 kernel32.OpenProcess.argtypes = [wintypes.DWORD, wintypes.BOOL, wintypes.DWORD] kernel32.OpenProcess.restype = wintypes.HANDLE kernel32.CloseHandle.argtypes = [wintypes.HANDLE] kernel32.CloseHandle.restype = wintypes.BOOL kernel32.CreateFileA.argtypes = [wintypes.LPCSTR, wintypes.DWORD, wintypes.DWORD, wintypes.LPVOID, wintypes.DWORD, wintypes.DWORD, wintypes.HANDLE] kernel32.CreateFileA.restype = wintypes.HANDLE dbghelp.MiniDumpWriteDump.argtypes = [wintypes.HANDLE, wintypes.DWORD, wintypes.HANDLE, wintypes.DWORD, wintypes.LPVOID, wintypes.LPVOID, wintypes.LPVOID] dbghelp.MiniDumpWriteDump.restype = wintypes.BOOL def create_full_dump(process_id, dump_path): # 打开进程 process_handle = kernel32.OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_DUP_HANDLE, False, process_id) if not process_handle: raise ctypes.WinError(ctypes.get_last_error()) # 创建转储文件 dump_file = kernel32.CreateFileA( dump_path.encode('utf-8'), 0x40000000, # GENERIC_WRITE 0, None, 2, # CREATE_ALWAYS 0x80, # FILE_ATTRIBUTE_NORMAL None ) if dump_file == wintypes.HANDLE(-1).value: kernel32.CloseHandle(process_handle) raise ctypes.WinError(ctypes.get_last_error()) # 写入转储 success = dbghelp.MiniDumpWriteDump( process_handle, process_id, dump_file, MiniDumpWithFullMemory | MiniDumpWithHandleData | MiniDumpWithUnloadedModules | MiniDumpWithProcessThreadData, None, None, None ) if not success: kernel32.CloseHandle(dump_file) kernel32.CloseHandle(process_handle) raise ctypes.WinError(ctypes.get_last_error()) # 清理资源 kernel32.CloseHandle(dump_file) kernel32.CloseHandle(process_handle) print(f"转储创建成功: {dump_path}") if __name__ == "__main__": target_process_id = 13940 create_full_dump(target_process_id, f"FullDump_{target_process_id}.dmp")
内容的提问来源于stack exchange,提问作者Max
相关产品推荐
相关产品推荐

