You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现与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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 17:42:04