📄 log.cpp
字号:
// LOG : implementation file for Exception Handling Functionality
#include "stdafx.h"
#include <eh.h>
#include "Log.h"
#ifndef __AFXDISP_H__ // COleException COleDispatchException
#include <afxdisp.h>
#endif
#ifndef __AFXTEMPL_H__ // Required for CArray
#include <afxtempl.h>
#endif
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
static void LogExceptionEx( CException *e ); // MFC Exception
static void LogExceptionEx( SEH_Exception &e ); // Win32 SEH Class
static void LogExceptionEx( _com_error &e ); // #import Class
static void LogExceptionEx( ); // Unhandled excep
// Prevent multiple "#ifndef _UNICODE" in this file...
#ifndef _UNICODE
#define VSPRINTF vsprintf
#define STRCHR strchr
#define STRLEN strlen
#define MFC_EXCEPTION _T("MFC Exception(%s) thrown:")
#define STR_FILE _T("\t FILE: %s")
#define STR_TIME _T("\t TIME: %s")
#define STR_MEANING _T("\tCode meaning = %s")
#define STR_SOURCE _T("\tSource = %s")
#define STR_DESCRIPTION _T("\tDescription = %s")
#define STR_TMP _T("%s")
#define STR_CAST (char *)
#else
#define VSPRINTF vswprintf
#define STRCHR wcschr
#define STRLEN wcslen
#define MFC_EXCEPTION _T("MFC Exception(%S) thrown:")
#define STR_FILE _T("\t FILE: %S")
#define STR_TIME _T("\t TIME: %S")
#define STR_MEANING _T("\tCode meaning = %S")
#define STR_SOURCE _T("\tSource = %S")
#define STR_DESCRIPTION _T("\tDescription = %S")
#define STR_TMP _T("%S")
#define STR_CAST (WCHAR *)
#endif // #ifndef _UNICODE
/////////////////////////////////////////////////////////////////////////////
// Local Data
/////////////////////////////////////////////////////////////////////////////
// Array of exceptions logged
static CArray<CString,CString> Errors;
// Message box telling user exception was thrown???
static BOOL bVerbose = TRUE;
/////////////////////////////////////////////////////////////////////////////
// Misc. Functions
/////////////////////////////////////////////////////////////////////////////
// Return CString with error message returned by HR
CString LogCrackHR( HRESULT hr )
{
LPVOID lpMsgBuf;
CString strTmp;
::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
hr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL );
strTmp.Format( STR_TMP, (char *) lpMsgBuf );
int i;
while ( (i=strTmp.Find('\r')) > -1 )
{
strTmp.SetAt(i, ' ' );
}
while ( (i=strTmp.Find('\n')) > -1 )
{
strTmp.SetAt(i, ' ' );
}
// Free the buffer.
::LocalFree( lpMsgBuf );
return strTmp;
}
static void MappingSEHtoCPPExceptions( unsigned int uExceptionCode, _EXCEPTION_POINTERS* )
{
// The System Exception will be passed throw here and
// thrown by this function.
throw SEH_Exception( uExceptionCode );
}
// Initialize Exception Handling
void LogEnable( BOOL bLogVerbose )
{
// Set Win32 Exceptions to be handled as C++ typed exceptions
_set_se_translator(MappingSEHtoCPPExceptions);
// Set Verbose flag
bVerbose = bLogVerbose;
}
// Dump contents of all exceptions logged via TRACE
void LogDisplay( void )
{
int nCount = Errors.GetSize();
if ( nCount > 0 )
{
for( int i = 0; i < nCount; i++ )
{
TRACE( _T("%s"), Errors.GetAt( i ) );
}
}
else
{
TRACE( _T("No Exceptions Logged(!)") );
}
}
// Dump contents of all exceptions logged to a provided list box.
void LogDisplay( CListBox &mListBox, BOOL bReset )
{
int nCount = Errors.GetSize();
if ( bReset == TRUE )
mListBox.ResetContent();
if ( nCount > 0 )
{
for( int i = 0; i < nCount; i++ )
{
mListBox.AddString( Errors.GetAt( i ) );
}
}
else
{
mListBox.AddString( _T("No Exceptions Logged(!)") );
}
}
// Empty list of logged exceptions
void LogReset( void )
{
Errors.RemoveAll();
}
/////////////////////////////////////////////////////////////////////////////
// Exception Logging Functions
/////////////////////////////////////////////////////////////////////////////
// Function to log a message, used just like printf
// This is used heavily by the LogException functions, but you can
// also use it to log your own messages as well.
void Log
(
LPCTSTR lpszFormat, // Message Format String
... // Variable Argument List
)
{
// Attempt to process info, and if unable to successfully use
// variable argument lists.
try
{
// Build error string
TCHAR lpszLogError[1024];
TCHAR *pchChar;
va_list marker;
va_start ( marker, lpszFormat );
VSPRINTF( lpszLogError, lpszFormat, marker );
va_end ( marker );
// remove \r and \n
while( (pchChar = STRCHR( lpszLogError, '\r' )) != NULL )
{
*pchChar = ' ';
}
while( (pchChar = STRCHR( lpszLogError, '\n' )) != NULL )
{
*pchChar = ' ';
}
Errors.Add( lpszLogError );
}
catch( CException *e )
{
Errors.Add( _T( "\t\t\t <<Unable to process error message info.>>" ) );
e->Delete();
}
catch( ... )
{
Errors.Add( _T( "\t\t\t <<Unable to process error message info.>>" ) );
}
}
// Functions to crack open exceptions called by LOG* Macros below.
// You probably wouldn't call these direct unless you were using
// your own try/catch block as opposed to the LOG* macros.
void LogException
(
CException *e, // MFC Exception
LPCSTR lpszTimeStamp, // Date & Time
LPCSTR lpszFile, // File Name
int nLine // Line #
)
{
// Just in case exception handling code throws an exception
try
{
// Step 1: Determine name of MFC Exception
CString strName;
CRuntimeClass *pClass = e->GetRuntimeClass();
ASSERT( pClass != NULL );
ASSERT( pClass->m_lpszClassName != NULL );
strName.Format( MFC_EXCEPTION, (LPCTSTR) pClass->m_lpszClassName );
Log( strName );
Log( STR_FILE, (LPCTSTR) lpszFile );
Log( _T("\t LINE #%d"), nLine );
Log( STR_TIME, (LPCTSTR) lpszTimeStamp );
}
catch( CException *e2 )
{
e2->Delete();
}
catch( ... )
{
}
LogExceptionEx( e );
}
void LogException
(
CException *e // MFC Exception
)
{
CString strName;
// Just in case exception handling code throws an exception
try
{
// Step 1: Determine name of MFC Exception
CString strName;
CRuntimeClass *pClass = e->GetRuntimeClass();
ASSERT( pClass != NULL );
ASSERT( pClass->m_lpszClassName != NULL );
strName.Format( MFC_EXCEPTION, (LPCTSTR) pClass->m_lpszClassName );
Log( strName );
}
catch( CException *e2 )
{
e2->Delete();
}
catch( ... )
{
}
LogExceptionEx( e );
}
static void LogExceptionEx
(
CException *e // MFC Exception
)
{
// Just in case exception handling code throws an exception
try
{
// For certain Exception classes, GetErrorMessage is supported
if ( ( e->IsKindOf( RUNTIME_CLASS( CArchiveException ) ) == TRUE ) ||
( e->IsKindOf( RUNTIME_CLASS( CFileException ) ) == TRUE ) ||
( e->IsKindOf( RUNTIME_CLASS( COleException ) ) == TRUE ) ||
( e->IsKindOf( RUNTIME_CLASS( COleDispatchException ) ) == TRUE ) )
{
TCHAR szBuf[256] = _T("");
UINT nHelpContextId;
BOOL bRetVal = TRUE;
e->GetErrorMessage( szBuf, 256, &nHelpContextId );
if( STRLEN( szBuf ) > 0 )
{
Log( _T("\t Error Message = %s"), szBuf );
}
}
// Individual Exception Information Handling
if ( e->IsKindOf( RUNTIME_CLASS( CArchiveException )) == TRUE )
{
CArchiveException *eArchive = (CArchiveException *) e;
switch( eArchive->m_cause )
{
case CArchiveException::none:
Log( _T("\t Cause = None (No error occurred)." ) );
break;
case CArchiveException::generic:
Log( _T("\t Cause = Generic (Unspecified error)." ) );
break;
case CArchiveException::readOnly:
Log( _T("\t Cause = ReadOnly (Tried to write into an archive opened for loading)." ) );
break;
case CArchiveException::endOfFile:
Log( _T("\t Cause = EndOfFile (Reached end of file while reading an object)." ) );
break;
case CArchiveException::writeOnly:
Log( _T("\t Cause = WriteOnly (Tried to read from an archive opened for storing)." ) );
break;
case CArchiveException::badIndex:
Log( _T("\t Cause = BadIndex (Invalid file format)." ) );
break;
case CArchiveException::badClass:
Log( _T("\t Cause = BadClass (Tried to read an object into an object of the wrong type)." ) );
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -