如何将Win32异常代码转换为字符串?

Ala*_*kes 12 c winapi seh

我不情愿地再次处理Win32结构化异常.我正在尝试生成描述异常的字符串.大多数都很简单,但我坚持一些基本的东西:如何将异常代码(结果GetExceptionCode()或者ExceptionCode成员EXCEPTION_RECORD)转换为描述异常的字符串?

我正在寻找能够将例如0xC0000005转换为"访问冲突"的内容.这只是一个电话FormatMessage()吗?

4Le*_*Cat 9

结构化异常代码通过NTSTATUS编号定义.虽然MS的某些人建议使用FormatMessage()将NTSTATUS数字转换为字符串,但我不会这样做.Flag FORMAT_MESSAGE_FROM_SYSTEM用于将GetLastError()的结果转换为字符串,因此这里没有意义.使用标志FORMAT_MESSAGE_FROM_HMODULE沿ntdll.dll将导致对某些代码不正确的结果.例如,因为EXCEPTION_ACCESS_VIOLATION你会得到The instruction at 0x,这不是很有用的信息:).

当你看到存储在ntdll.dll其中的字符串时,很明显很多字符串应该与printf()函数一起使用,而不是与FormatMessage()一起使用.例如,字符串为EXCEPTION_ACCESS_VIOLATION:

The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s.

%0FormatMessage()作为转义序列处理,表示消息终止符,而不是插入.插入是%1到%99.这就是旗帜FORMAT_MESSAGE_IGNORE_INSERTS没有任何区别的原因.

您可能希望加载从字符串ntdll.dll,并将它传递给vprintf,但你需要准备完全相同的参数作为字符串指定(例如EXCEPTION_ACCESS_VIOLATION它的unsigned long,unsigned long,char*).这种方法有一个主要缺点:参数的数量,顺序或大小的任何变化都ntdll.dll可能会破坏您的代码.

因此,将字符串硬编码到您自己的代码中更安全,更容易.我发现使用别人准备的字符串而不与我协调是危险的:)而且还有其他功能.这只是故障的另一种可能性.


MSa*_*ers 5

是。这是NTSTATUS,因此请使用FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_FROM_HMODULE,并HMODULE从传递LoadLibrary("NTDLL.DLL")

来源:KB259693(已存档)

  • 请参阅我的答案,我解释了为什么 FormatMessage 不能用于此目的。 (2认同)
  • [来源](http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q259693) 不存在。 (2认同)

Laa*_*Laa 5

正确管理某些 NTSTATUS 字符串所具有的流格式很复杂。您应该考虑使用RtlNtStatusToDosError()将其转换为 Win32 消息,该消息位于 header Winternl.h 中。您需要在链接器输入中包含 ntdll.lib。

实施示例:

// Returns length of resulting string, excluding null-terminator.
// Use LocalFree() to free the buffer when it is no longer needed.
// Returns 0 upon failure, use GetLastError() to get error details.
DWORD FormatNtStatus(NTSTATUS nsCode, TCHAR **ppszMessage) {

    // Get handle to ntdll.dll.
    HMODULE hNtDll = LoadLibrary(_T("NTDLL.DLL"));

    // Check for fail, user may use GetLastError() for details.
    if (hNtDll == NULL) return 0;

    // Call FormatMessage(), note use of RtlNtStatusToDosError().
    DWORD dwRes = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE,
        hNtDll, RtlNtStatusToDosError(nsCode), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR)ppszMessage, 0, NULL);

    // Free loaded dll module and decrease its reference count.
    FreeLibrary(hNtDll);

    return dwRes;
}
Run Code Online (Sandbox Code Playgroud)