0

处理错误的正确方法是什么?我有如下代码,处理我在 MSDN 上找到的所有错误代码,但有时我收到错误“未知”。

HRESULT hr = pwb->Navigate2(&URL, &Flag, &TargetFrameName, &PostData, &Headers);
if(FAILED(hr))
{
    std::string message("Navigate2 failed with reason: ");
    switch(hr)
    {
        // The operation was successful.
        case S_OK:
            message.append("S_OK");
            break;
        // One or more parameters are invalid.
        case E_INVALIDARG:
            message.append("E_INVALIDARG");
            break;
        // Out of memory.
        case E_OUTOFMEMORY:
            message.append("E_OUTOFMEMORY");
            break;
        // The operation failed.
        case E_FAIL:
            message.append("E_FAIL");
            break;
        case E_ACCESSDENIED:
            message.append("E_ACCESSDENIED");
            break;
        case E_POINTER:
            message.append("E_POINTER");
            break;
        case E_UNEXPECTED:
            message.append("E_UNEXPECTED");
            break;
        default:
            message.append("Unknown");
    }
}
4

2 回答 2

1

如何处理 COM 错误有很多变化。策略包括使用级联if SUCCEEDED()或集中式函数错误处理goto on FAILED()等。MSDN上有一些很好的信息。

至于解释错误代码,FormatMessage()通常会使您的工作更轻松 - 这是MSDN的一个示例(为了清楚起见,包括在下面)

[来源: http: //msdn.microsoft.com/en-us/library/windows/desktop/ms687061(v=vs.85).aspx]

    #include <stdio.h>
    #include <windows.h>
    #include <tchar.h>

    void ErrorDescription(HRESULT hr) 
    { 
         if(FACILITY_WINDOWS == HRESULT_FACILITY(hr)) 
             hr = HRESULT_CODE(hr); 
         TCHAR* szErrMsg; 

         if(FormatMessage( 
           FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, 
           NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
           (LPTSTR)&szErrMsg, 0, NULL) != 0) 
         { 
             _tprintf(TEXT("%s"), szErrMsg); 
             LocalFree(szErrMsg); 
         } else 
             _tprintf( TEXT("[Could not find a description for error # %#x.]\n"), hr); 
    }

在上面的调用中,标志表明 Windows 将为错误消息分配内存(您必须自由使用LocalFree()),并且它将在系统消息表(FORMAT_MESSAGE_FROM_SYSTEM)中查找错误消息。有时,(或通常取决于您使用的库类型) - 在系统消息表中找不到相应的错误描述。

在这种情况下,您可以自己处理错误描述(如您在示例中所做的那样)或尝试直接加载库的消息表。为此,请使用FORMAT_MESSAGE_FROM_HMODULE并提供模块句柄作为函数的lpSource参数FormatMessage()

这是一个例子:

std::wstring StackExample::getLastError( HRESULT hr ) 
{
    LPWSTR lpMsgBuf;
    DWORD ret;
    std::wstring def(L"(UNKNOWN)");
    ret = FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_HMODULE,
        GetModuleHandle(TEXT("imapi2.dll")),
        hr,
        0,
        (LPWSTR) &lpMsgBuf,
        0, NULL );

    if(ret)
    {
        std::wstring last(lpMsgBuf);
        LocalFree(lpMsgBuf);
        return last;
    }
    return def;
}
于 2012-12-21T07:41:37.623 回答
0

HRESULT错误代码实际上是LONG带有具有单独含义的位块的类型。也就是说,处理switch语句中的每个错误是不现实的。

如果你对特定的错误代码有特定的处理,你就去做。否则,您通常使用SUCCEEDEDFAILED宏检查返回的成功/失败:

if(FAILED(nResult))
{
  // TODO: Handle the failed operation here
}

另请参阅:COM 中的错误代码

要检查 COM 方法是否成功,请检查返回的 HRESULT 的高位。Windows SDK 标头提供了两个使这更容易的宏:SUCCEEDED 宏和 FAILED 宏。如果 HRESULT 是成功代码,SUCCEEDED 宏返回 TRUE,如果是错误代码,则返回 FALSE。

于 2012-12-21T06:47:48.443 回答