質問

What is the correct way to handle errors? I've code like following, handling all error codes I've found on MSDN and still, sometimes, I've received error "Unknown".

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");
    }
}
役に立ちましたか?

解決

There's quite a few variations on how to handle COM errors. Strategies include use of cascading if SUCCEEDED() or centralized function error handling using goto on FAILED() among others. There's some good information on MSDN.

As to interpreting error codes, FormatMessage() will often make your work easier - here's an example from MSDN (included below for clarity)

[Source: 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); 
    }

In the call above, the flags indicate that windows will allocate memory for error messages (which you have to free - use LocalFree()) and that it will look for error messages in the system message tables (FORMAT_MESSAGE_FROM_SYSTEM). Sometimes, (or often depending on the kind of libraries you use) - no corresponding error descriptions will be found in the system message tables.

In cases like these you may either handle the error description yourself (as you have done in your example) or attempt to load a library's message tables directly. To do this, use the FORMAT_MESSAGE_FROM_HMODULE and supply a module handle as the lpSource parameter to the FormatMessage() function.

Here's an example:

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;
}

他のヒント

HRESULT error codes are actually LONG type with blocks of bits having individual meaning. That is, it is unrealistic to handle every error in switch statement.

If you have specific handling for specific error code, you do it. Otherwise you normally check the returned for success/failure using SUCCEEDED and FAILED macros:

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

See also: Error Codes in COM:

To check whether a COM method succeeds, examine the high-order bit of the returned HRESULT. The Windows SDK headers provide two macros that make this easier: the SUCCEEDED macro and the FAILED macro. The SUCCEEDED macro returns TRUE if an HRESULT is a success code and FALSE if it is an error code.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top