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

Windows下如何通过IDebugClient编程从dump文件中获取进程名称

Windows调试API直接获取进程名及崩溃相关模块名的方案

1 获取PROCESS_NAME

PROCESS_NAME对应Dump文件中被调试进程的主可执行文件名称,有两种可靠实现方式,优先级从高到低:

1.1 直接调用系统对象接口获取(最优方案)

通过IDebugSystemObjects4接口的GetCurrentProcessExecutableName方法直接获取,返回结果和WinDbg的!analyze -v输出的PROCESS_NAME完全一致,不需要遍历模块。
示例代码:

#include <dbgeng.h>
#pragma comment(lib, "dbgeng.lib")

// 此处省略IDebugClient、IDebugControl等基础接口初始化逻辑
IDebugSystemObjects4* pSysObj = nullptr;
HRESULT hr = pDebugClient->QueryInterface(__uuidof(IDebugSystemObjects4), (void**)&pSysObj);
if (SUCCEEDED(hr)) {
    char procName[MAX_PATH] = {0};
    ULONG nameSize = 0;
    hr = pSysObj->GetCurrentProcessExecutableName(procName, MAX_PATH, &nameSize);
    if (SUCCEEDED(hr)) {
        // procName即为所需的PROCESS_NAME
        printf("PROCESS_NAME: %s\n", procName);
    }
    pSysObj->Release();
}

1.2 遍历模块兜底方案

如果部分精简Minidump不支持上述接口,可以通过以下逻辑定位主模块:

  • 调用IDebugSystemObjects::GetCurrentProcessPeb获取进程PEB地址,读取PEB的ImageBaseAddress字段拿到主模块基址
  • 用拿到的主模块基址调用GetModuleNames获取可执行文件名,结果和PROCESS_NAME一致

2 获取IMAGE_NAME和MODULE_NAME

WinDbg的!analyze -v输出中,IMAGE_NAME是触发崩溃的指令所在模块的完整镜像名,MODULE_NAME是该模块的短名称,获取逻辑如下:

  1. 调用IDebugControl::GetLastEventInformation获取崩溃事件的异常信息,拿到崩溃发生时的指令指针(RIP/EIP/PC)
  2. 调用IDebugSymbols3::GetModuleByOffset,传入指令指针地址,查询到该地址所属的模块基址和索引
  3. 调用GetModuleNames传入上述模块基址,返回的ImageNameBuffer即为IMAGE_NAME,ModuleNameBuffer即为MODULE_NAME
    示例代码:
DEBUG_LAST_EVENT_INFO_EXCEPTION exceptionInfo = {0};
ULONG infoSize = 0;
// 先查询异常信息大小
hr = pDebugControl->GetLastEventInformation(NULL, NULL, NULL, 0, NULL, &infoSize, NULL, 0, NULL);
if (SUCCEEDED(hr) && infoSize >= sizeof(DEBUG_LAST_EVENT_INFO_EXCEPTION)) {
    // 读取异常详情
    hr = pDebugControl->GetLastEventInformation(NULL, NULL, NULL, sizeof(exceptionInfo), &exceptionInfo, NULL, NULL, 0, NULL);
    if (SUCCEEDED(hr)) {
        ULONG64 crashIp = (ULONG64)exceptionInfo.ExceptionRecord.ExceptionAddress;
        ULONG moduleIndex = 0;
        ULONG64 moduleBase = 0;
        // 根据崩溃指令地址查询所属模块
        hr = pSymbols->GetModuleByOffset(crashIp, 0, &moduleIndex, &moduleBase);
        if (SUCCEEDED(hr)) {
            char ImageNameBuffer[MAX_PATH] = {0}, ModuleNameBuffer[MAX_PATH] = {0};
            ULONG ImageNameSize = 0, ModuleNameSize = 0;
            hr = pSymbols->GetModuleNames(DEBUG_ANY_ID, moduleBase, 
                ImageNameBuffer, MAX_PATH, &ImageNameSize,
                ModuleNameBuffer, MAX_PATH, &ModuleNameSize,
                NULL, 0, NULL);
            if (SUCCEEDED(hr)) {
                printf("IMAGE_NAME: %s\n", ImageNameBuffer);
                printf("MODULE_NAME: %s\n", ModuleNameBuffer);
            }
        }
    }
}

注意事项

不要直接遍历所有模块按索引取名称,只有定位到对应业务场景的模块(主进程模块/崩溃触发模块)后查询的名称,才会和WinDbg的!analyze输出完全匹配。

内容的提问来源于stack exchange,提问作者Infant

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 09:12:02