C++实现一个简单的异常日志记录类

头文件
#pragma once
/////////////////////////////////////////////////////////////////////////////////
//异常信息记录类

#include <string>
#ifdef UNICODE
#define tstring std::wstring
#else
#define tstring std::string
#endif

//定义异常信息结构体
typedef struct _EXCEPTION_INFO
{
    tstring tstrExceptionInfo;//异常信息字符串
    int     nExceptionLine;    //出现异常的代码行
}EXCEPTION_INFO,LPEXCEPTION_INFO;

//填充异常结构体
inline EXCEPTION_INFO FillExceptionInfo(TCHAR* pInfo,int nLine)
{
    EXCEPTION_INFO ei;
    ei.tstrExceptionInfo.append(pInfo);
    ei.nExceptionLine=nLine;
    return ei;
}

class _declspec(dllexport) CErrorLog
{
public:
    CErrorLog(TCHAR* pModuleName);
    virtual~ CErrorLog();
    //记录异常,参数依次为函数名、错误信息、模块名
    bool WriteErrorLog(tstring& tstrFuncName,int nLine,tstring& tstrErrorMsg=tstring(_T("")),tstring& tstrModuleName=tstring(_T("")));
    bool WriteErrorLog(TCHAR* pFuncName,int nLine,TCHAR* pErrorMsg=NULL,TCHAR* pModuleName=NULL);
protected:
    /********************受保护的成员函数**********************/
    //记录自身异常
    bool WriteOwerErrorLog( tstring& tstrFunName, tstring& tstrErrMsg,int nLine);
    bool WriteOwerErrorLog(TCHAR* strFuncName,TCHAR* pErrorMsg,int nLine);
    //格式化当前时间
    inline std::string FormatTime();
    //获取系统错误信息
    inline std::string FormatLastError();
private:
    //保存当前模块的名称
    tstring m_strModuleName;
};
 
实现
 
 
#include "stdafx.h"
#include "CodeConvert.h"
#include "ErrorLog.h"
#include <time.h>
#include <assert.h>

CErrorLog::CErrorLog(TCHAR* pModuleName)
{
    assert(pModuleName);
    m_strModuleName.append(pModuleName);
}
CErrorLog::~CErrorLog()
{

}
bool CErrorLog::WriteOwerErrorLog(TCHAR* pFuncName,TCHAR* pErrorMsg,int nLine)
{
    return WriteErrorLog(pFuncName,nLine,pErrorMsg,_T("CErrorLog"));
}

bool CErrorLog::WriteOwerErrorLog(tstring& tstrFunName, tstring& tstrErrMsg,int nLine )
{
    return WriteErrorLog(tstrFunName,nLine,tstrErrMsg,tstring(_T("CErrorLog")));
}

bool CErrorLog::WriteErrorLog(TCHAR* pFuncName,int nLine,TCHAR* pErrorMsg,TCHAR* pModuleName)
{
    bool bRet=true;
    try
    {
        assert(pFuncName);
        if(NULL!=pErrorMsg)
        {
            std::string strExcep;
            std::string strFuncName;
#ifdef UNICODE
            strFuncName.append(CCodeCovert::WcharToChar(pFuncName));
            strExcep.append(CCodeCovert::WcharToChar(pErrorMsg));
#else
            strFuncName.append(pFuncName);
            strExcep.append(pErrorMsg);
#endif
            TCHAR szPath[MAX_PATH+1]={0};
            GetModuleFileName(NULL,szPath,MAX_PATH);
            int nDes=-1;
            for(size_t i=0;i<_tcslen(szPath);++i)
            {
                if('\'==szPath[i])
                    nDes=i;
            }
            szPath[nDes+1]='';
            _tcscat(szPath,_T("ErrorLogs\"));
            ::CreateDirectory(szPath,NULL);
            if(NULL!=pModuleName)
            {
                _tcscat(szPath,pModuleName);
                _tcscat(szPath,_T(".log"));
            }
            else
            {
                tstring strTemp=m_strModuleName;
                strTemp.append(_T(".log"));
                _tcscat(szPath,strTemp.c_str());
            }
            FILE* fp=_tfopen(szPath,_T("a+"));
            char* pBuffer="*************************************************************************
";
            int nRet=fwrite(pBuffer,strlen(pBuffer),1,fp);
            pBuffer="系统时间:";
            fwrite(pBuffer,strlen(pBuffer),1,fp);
            std::string strTime=FormatTime();
            //strTime.append("
");
            fwrite(strTime.c_str(),strTime.size(),1,fp);
            pBuffer="文件路径:";
            fwrite(pBuffer,strlen(pBuffer),1,fp);
            char szSourcePath[MAX_PATH+2]={0};
            sprintf(szSourcePath,"%s
",__FILE__);
            fwrite(szSourcePath,strlen(szSourcePath),1,fp);
            pBuffer="异常行数:";
            fwrite(pBuffer,strlen(pBuffer),1,fp);
            char szLine[7]={0};
            sprintf(szLine,"%d
",nLine);
            fwrite(szLine,strlen(szLine),1,fp);
            pBuffer="异常函数:";
            fwrite(pBuffer,strlen(pBuffer),1,fp);
            strFuncName.append("
");
            fwrite(strFuncName.c_str(),strFuncName.size(),1,fp);
            pBuffer="异常信息:";
            fwrite(pBuffer,strlen(pBuffer),1,fp);
            strExcep.append("
");
            fwrite(strExcep.c_str(),strExcep.size(),1,fp);
            std::string strSyserror=FormatLastError();
            fwrite(strSyserror.c_str(),strSyserror.size(),1,fp);
            fclose(fp);
        }
    }
    catch(EXCEPTION_INFO& except)
    {
        bRet=false;
        WriteOwerErrorLog(tstring(_T("WriteErrorLog")),except.tstrExceptionInfo,except.nExceptionLine);
    }
    return bRet;
}

bool CErrorLog::WriteErrorLog( tstring& tstrFuncName,int nLine,tstring& tstrErrorMsg/*=tstring(_T(""))*/,tstring& tstrModuleName/*=tstring(_T(""))*/ )
{
    return WriteErrorLog((TCHAR*)tstrFuncName.c_str(),nLine,(TCHAR*)tstrErrorMsg.c_str(),
       (TCHAR*)tstrModuleName.c_str());
}

std::string CErrorLog::FormatLastError()
{
    std::string strRet("系统错误:");
    try
    {
        LPVOID lpErrorMsg=NULL; 
        FormatMessage(
            FORMAT_MESSAGE_ALLOCATE_BUFFER | 
            FORMAT_MESSAGE_FROM_SYSTEM | 
            FORMAT_MESSAGE_IGNORE_INSERTS, 
            NULL, 
            GetLastError(), 
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language 
            (LPTSTR)&lpErrorMsg, 
            0, 
            NULL 
            );
        tstring tstrError((LPTSTR)lpErrorMsg);
#ifdef UNICODE
        std::string strError=CCodeCovert::WstringToString(tstrError);
        strRet+=strError;
#else
        strRet+=tstrError;
#endif
        ::LocalFree(lpErrorMsg);
    }
    catch(TCHAR* pError)
    {
        WriteOwerErrorLog(_T("FormatLastError"),pError,__LINE__);
    }
    return strRet;
}
std::string CErrorLog::FormatTime()
{
    std::string strRet;
    try
    {
        tm* st;
        time_t time64=time(NULL);
        st=localtime(&time64);
        strRet.append(asctime(st));
    }
    catch(TCHAR* pError)
    {
    
        WriteOwerErrorLog(_T("FormatTime"),pError,__LINE__);
        strRet.clear();
    }
    return strRet;
}
 

该类对基本的文件操作,错误信息获取,系统时间获取等进行了封装,使用的时候也是很简单的。

测试:

 

#include "stdafx.h"
#include <iostream>
#include "ErrorLog.h"
class CarBase:public CErrorLog
{
public:
    CarBase()
        :CErrorLog(_T("CarBase"))
    {



         if(1)
             WriteErrorLog(_T("CarBase"),__LINE__-1,_T("测试错误!!!!"));
    }
public:
    void Init()
    {
        CarBase();
    }
};
class Car:public CarBase
{

};
int _tmain(int argc, _TCHAR* argv[])
{
    CarBase cb;
    int nlen=0;
    nlen=sizeof(CarBase);
    std::cout<<"类CarBase的大小为:"<<nlen<<std::endl;
    for(int i=0;i<100;++i)
        cb.WriteErrorLog(_T("MAIN"),__LINE__,_T("不知道的问题"),_T("模块"));
    return 0;
/*    _onexit()*/
}
原文地址:https://www.cnblogs.com/lizs/p/3642208.html