C++は簡単な異常ログ記録クラスを実現する
7786 ワード
#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]='\0';
_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\r
",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()*/
}
能力が限られているので,批判と指導を歓迎する.