본문 바로가기

3.구현/VC++

VC에서 윈도우 에러메시지

윈도우에서 에러 코드는 얻는 함수는 GetLastError()이다. 이함수를 사용하여 얻는 값는 숫자로 되어 있다. 숫자로만은 어떤 에러인지 알수 없다. 물론 구글링하면 되겠지만, 번거롭다. 또는 에러 코드마다 에러메시지 생성을 해주어야 하는 귀찮은 일이 생긴다.

이를 간단하게 해결할 수 있는 방법이 에러 코드를 이용해서 자동으로 에러 메시지를 생성하는 것이다. 이를 위한 win32 api가 FormatMessage()가 있다.

CString ErrorString(DWORD err)
{
    std::ostringstrm ostm;
    LPTSTR s;
    if(::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM,
        NULL,
        err,
        0,
        (LPTSTR)&s,
        0,
        NULL) == 0)
    { /* failed */
        // Unknown error code %08x (%d)
        CString fmt;
        CString t;
        //fmt.LoadString("Unknown Error.");
        fmt = "Unknown Error.";
        t.Format(fmt, err, LOWORD(err));
        Error = t;
    } /* failed */
    else
    { /* success */
        LPTSTR p = _tcschr(s, _T('\r'));
        if(p != NULL)
        { /* lose CRLF */
            *p = _T('\0');
        } /* lose CRLF */
        Error = s;
        ::LocalFree(s);
    } /* success */
    return Error;
} // ErrorString

위의 버전은 C++용이라고 할 수 있다. C에서 맞게 수정해보았다.

주의할 것은 반환되는 값은 static 문자열이기 때문에 에러 문자열을 보고하고 싶다면,

따로 할당해서 별도로 보관해야 한다. 그리고, 다른 곳에서 동시데 ErrorString에 접근할 경우 잘못된 에러 메시지가 나올 수 도 있다.

// required header: Windows.h, stdio.h
char* ErrorString(DWORD err)  
{  
    static char err_msg[512];
    size_t len = sizeof(err_msg);
    LPTSTR s; 
    if( FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |  
        FORMAT_MESSAGE_FROM_SYSTEM,  
        NULL,  
        err,  
        0,  
        (LPTSTR)&s,  
        0,
        NULL) == 0)  
    { // Fail: Unknown error code %08x (%d)
        _snprintf (err_msg, len, "Unknown Error %d", LOWORD(err));
    } else {
        // success
        LPTSTR p = _tcschr(s, _T('\r'));  
        if(p != NULL) {
            // CRLF을 제거
            *p = _T('\0');  
        }
        _snprintf (err_msg, len, "%s", s);
        LocalFree(s);  
    }  
    return err_msg;
}

참조:

[1] FormatMessage Function, http://msdn.microsoft.com/en-us/library/ms679351(VS.85).aspx

반응형