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

如何在程序运行时获取Visual Studio中NetworkDirect HRESULT状态码的错误文本?

Windows状态常量转人类可读错误信息的实现方案

问题背景

尝试将Windows状态常量(如STATUS_ACCESS_VIOLATION、ND_ACCESS_VIOLATION)转换为可读错误信息时,使用_com_error的ErrorMessage()方法仅能正确处理COM标准HRESULT(如E_FAIL),其他状态码均返回"Unknown error",但Visual Studio监视窗口能显示正确描述,需要在运行时获取这些文本。

原代码及输出

原代码

#include <Windows.h>
#include <comdef.h>

#include <iostream>

// from ndstatus.h
#define ND_ACCESS_VIOLATION              ((HRESULT)0xC0000005L)
#define ND_INVALID_PARAMETER_3           ((HRESULT)0xC00000F1L)

int main() {
    const HRESULT hr1 = E_FAIL;
    std::cout << _com_error(hr1).ErrorMessage() << std::endl;

    const HRESULT hr2 = STATUS_ACCESS_VIOLATION;
    std::cout << _com_error(hr2).ErrorMessage() << std::endl;

    const HRESULT hr3 = ND_ACCESS_VIOLATION;
    std::cout << _com_error(hr3).ErrorMessage() << std::endl;

    const HRESULT hr4 = ND_INVALID_PARAMETER_3;
    std::cout << _com_error(hr4).ErrorMessage() << std::endl;
}

输出结果

Unspecified error
Unknown error 0xC0000005
Unknown error 0xC0000005
Unknown error 0xC00000F1

问题原因

_com_error仅针对COM定义的HRESULT设计,无法识别NTSTATUS转换而来的HRESULT(如STATUS_*系列、ND_*系列)。Visual Studio监视窗口能正确显示是因为它调用了系统底层的错误信息查询接口。

解决方案:使用FormatMessage函数

Windows API的FormatMessage可以从系统错误资源中提取所有NTSTATUS和HRESULT对应的描述文本。以下是实现代码:

#include <Windows.h>
#include <iostream>
#include <string>

// from ndstatus.h
#define ND_ACCESS_VIOLATION              ((HRESULT)0xC0000005L)
#define ND_INVALID_PARAMETER_3           ((HRESULT)0xC00000F1L)

std::wstring GetErrorText(HRESULT hr) {
    wchar_t* msgBuffer = nullptr;
    // 处理NTSTATUS转HRESULT的情况:如果是0xC0000000开头的HRESULT,直接用原始DWORD值查询
    DWORD status = (hr & 0xFFFFF000) == 0xC0000000 ? static_cast<DWORD>(hr) : HRESULT_CODE(hr);
    
    DWORD result = FormatMessageW(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
        nullptr,
        status,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        reinterpret_cast<LPWSTR>(&msgBuffer),
        0,
        nullptr
    );

    if (result == 0) {
        // 系统无对应描述时,返回十六进制错误码
        wchar_t hexBuffer[32];
        swprintf_s(hexBuffer, L"Unknown error 0x%08X", hr);
        return hexBuffer;
    }

    std::wstring errorMsg(msgBuffer);
    LocalFree(msgBuffer);
    // 移除末尾的换行符,优化输出格式
    if (!errorMsg.empty() && errorMsg.back() == L'\n') {
        errorMsg.pop_back();
        if (!errorMsg.empty() && errorMsg.back() == L'\r') {
            errorMsg.pop_back();
        }
    }
    return errorMsg;
}

int main() {
    const HRESULT hr1 = E_FAIL;
    std::wcout << GetErrorText(hr1) << std::endl;

    const HRESULT hr2 = STATUS_ACCESS_VIOLATION;
    std::wcout << GetErrorText(hr2) << std::endl;

    const HRESULT hr3 = ND_ACCESS_VIOLATION;
    std::wcout << GetErrorText(hr3) << std::endl;

    const HRESULT hr4 = ND_INVALID_PARAMETER_3;
    std::wcout << GetErrorText(hr4) << std::endl;

    return 0;
}

代码说明

  1. 类型适配:针对0xC0000000开头的HRESULT(本质是NTSTATUS),直接使用原始DWORD值查询;普通HRESULT则提取错误码部分。
  2. FormatMessage参数:
    • FORMAT_MESSAGE_ALLOCATE_BUFFER:让系统自动分配存储错误信息的缓冲区
    • FORMAT_MESSAGE_FROM_SYSTEM:从系统内置的错误资源中读取描述文本
    • FORMAT_MESSAGE_IGNORE_INSERTS:跳过格式化占位符,避免额外参数处理
  3. 资源管理:使用LocalFree释放系统分配的缓冲区,防止内存泄漏
  4. 文本优化:移除错误信息末尾的换行符,让输出更整洁

预期输出

Unspecified error
Access violation
Access violation
Invalid parameter 3

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 01:35:06