Class for displaying system error messages

The attached zip contains a small class I use regularly. It is an interface to the win32 FormatMessage api for error-reporting.

It's use is very simple: when you detect a win32 error (could not open file for example):

FILE *f = fopen("idontexist.txt", "r");
if(!f)
{
   CErrorMessage em;  // initializes with the current ::GetLastError
   if(em.MessageBox("problem opening file, cause:", "file:idontexist.txt\nRetry?", MB_YESNO)== IDYES)
   {
	...
   }
}

Header file.
// ErrorMessage.h: interface for the CErrorMessage class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_ERRORMESSAGE_H__51CAC9F1_9ECE_11D1_A06C_0000832CDDC7__INCLUDED_)
#define AFX_ERRORMESSAGE_H__51CAC9F1_9ECE_11D1_A06C_0000832CDDC7__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

class CErrorMessage  
{
public:
		// default ctor: calls GetLastError to get the current errorcode
	CErrorMessage();
		// specify your own errorcode
	CErrorMessage(DWORD theError);
	~CErrorMessage();

		//	setup a new error (0=call GetLastError)
	void	setError(DWORD error=0);

	CString	getMessage() const		{return themsg;}
	DWORD	getMessageCode() const	{return dwError;}
		//	AfxMessageBox with the text pfxtext + "\n" + themsg + "\n" + suftext
	int		MessageBox(const char* pfxtext=NULL, const char* suftext=NULL, UINT nType=MB_OK) const;
protected:
	DWORD	dwError;
	CString	themsg;
		//	get the messagestring from the system
	void	getCurrentMessage();

};

#endif // !defined(AFX_ERRORMESSAGE_H__51CAC9F1_9ECE_11D1_A06C_0000832CDDC7__INCLUDED_)

Implementation file.

// ErrorMessage.cpp: implementation of the CErrorMessage class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ErrorMessage.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
/*
	default ctor
	gets the current system-error
*/
CErrorMessage::CErrorMessage()
{
	dwError		=	::GetLastError();
	getCurrentMessage();
}
/*
	ctor
	you specify the system-error
*/
CErrorMessage::CErrorMessage(DWORD theError)
{
	dwError		=	theError;
	getCurrentMessage();
}

CErrorMessage::~CErrorMessage()
{
}
/*
	reuse an existing CErrorMessage by setting a new system-error
*/
void	CErrorMessage::setError(DWORD error)
{
	if(dwError==0)
		dwError=::GetLastError();
	else
		dwError=error;
	getCurrentMessage();
}
/*
	show a message-box with the error-message
	you can specify a prefix- and suffix-line to the message
*/
int CErrorMessage::MessageBox(const char* pfxtext, const char* suftext, UINT nType) const
{
	CString	msg	=	"";
	if(pfxtext)	msg	=	CString(pfxtext) + "\n";
	msg	+=	themsg;
	if(suftext)	msg	=	msg + "\n" + suftext;
	return AfxMessageBox(msg, nType);
}
/*
	get the message from the current errorcode in the user's language
*/
void CErrorMessage::getCurrentMessage()
{
	LPTSTR	lpBuf;
	if(::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
						FORMAT_MESSAGE_ALLOCATE_BUFFER
					,	NULL
					,	dwError
					,	MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT)
					,	(LPTSTR)&lpBuf
					,	0
					,	NULL)!=0)
	{
		themsg	=	lpBuf;
		::LocalFree(lpBuf);
	}
	else
	{
		themsg.Format("Error %i occurred (no further info)", dwError);
	}
}



Comments

  • Convert more OS error to string

    Posted by Legacy on 02/18/1999 12:00am

    Originally posted by: Remon

    Please have a look ...
    
    

    #include <lmerr.h>
    void PASCAL ConvertErrorToString( DWORD error_code, CString& error_string )
    {
    HMODULE hModule = NULL; // default to system source
    LPTSTR MessageBuffer = NULL;
    DWORD dwBufferLength;

    //
    // Always start off with an empty string
    //
    error_string.Empty();

    //
    // if error_code is in the network range, load the message source
    //
    if (error_code >= NERR_BASE && error_code <= MAX_NERR) {
    hModule = ::LoadLibraryEx( _TEXT("netmsg.dll"), NULL, LOAD_LIBRARY_AS_DATAFILE );
    }

    //
    // call FormatMessage() to allow for message text to be acquired
    // from the system or the supplied module handle
    //
    dwBufferLength = ::FormatMessage(
    FORMAT_MESSAGE_ALLOCATE_BUFFER |
    FORMAT_MESSAGE_IGNORE_INSERTS |
    FORMAT_MESSAGE_FROM_SYSTEM | // always consider system table
    ((hModule != NULL) ? FORMAT_MESSAGE_FROM_HMODULE : 0),
    hModule, // module to get message from (NULL == system)
    error_code,
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
    (LPTSTR) &MessageBuffer, 0, NULL );

    if ( MessageBuffer ) {
    if ( dwBufferLength )
    error_string = (LPCTSTR)MessageBuffer;

    //
    // free the buffer allocated by the system
    //
    ::LocalFree(MessageBuffer);
    }

    //
    // if you loaded a message source, unload it
    //
    if (hModule != NULL)
    ::FreeLibrary(hModule);

    if ( error_string.GetLength() == 0 ) {
    error_string.Format( TEXT( "Unknown System Error %lu" ), error_code );
    }
    }

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Ever-increasing workloads and the challenge of containing costs leave companies conflicted by the need for increased processing capacity while limiting physical expansion. Migration to HP's new generation of increased-density rack-and-blade servers can address growing demands for compute capacity while reducing costly sprawl. Sponsored by: HP and Intel® Xeon® processors Intel, the Intel logo, and Xeon Inside are trademarks of Intel Corporation in the U.S. and/or other countries. HP is the sponsor …

  • With JRebel, developers get to see their code changes immediately, fine-tune their code with incremental changes, debug, explore and deploy their code with ease (both locally and remotely), and ultimately spend more time coding instead of waiting for the dreaded application redeploy to finish. Every time a developer tests a code change it takes minutes to build and deploy the application. JRebel keeps the app server running at all times, so testing is instantaneous and interactive.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds