클라이언트가 프로그램 사용 중 오류가 발생했을 때 원인을 확인하기 위해 Log 정보를 텍스트 파일로 저장할 수 있도록 하는 것이 좋다.
검색으로 찾은 내용을 후에 다시 사용하기 위해 글로 작성해두려고 한다.
- 기존 코드로 실행하고 Log를 남겼을 때 문자열이 깨지는 현상이 있어 한 부분을 수정했다.
-> 기존 코드 strLog += szLog;
수정 후 : strLog += (Cstring)fmt;
-> 혹은 Multibyte <-> Unicode 변환으로도 가능합니다.
<stdafx.h>
extern CCriticalSection g_criticalLog;
extern CCriticalSection g_criticalDbg;
extern CCriticalSection g_criticalExe;
//가변인수함수로 Log 함수 선언
void Log(int nType, const char* fmt, ...);
CString GetFilePath();
// Log Type
enum LogType
{
Debug = 0, // 디버그
Normal, // 정상
End, // 끝
Error // 에러
};
<stdafx.cpp>
CCriticalSection g_criticalLog;
CCriticalSection g_criticalExe;
void Log(int nType, const char* fmt, ...)
{
g_criticalLog.Lock();
static _TCHAR szLog[5096];
FILE *fp = NULL;
CTime tm = CTime::GetCurrentTime();
CString strLog = _T("");
CString strPath = _T("");
va_list args; //가변 변수를 읽기 위한 포인터 변수
SYSTEMTIME cur_time;
if (fmt == NULL)
{
g_criticalLog.Unlock();
return;
}
ZeroMemory(szLog, 5096);
#if 0 Multibyte
va_start(args, fmt);
wvsprintf(szLog, (LPCWSTR)fmt, args);
va_end(args);
#else
MultiByteToWideChar(CP_ACP, 0, fmt, -1, szLog, 1024);
#endif
strPath.Format(_T("%s\\MainLog\\%s"), GetFilePath(), tm.Format("%Y_%m_%d_%H.log"));
fopen_s(&fp, (CStringA)strPath, "a+");
GetLocalTime(&cur_time);
strLog.Format(_T("%04d-%02d-%02d %02d:%02d:%02d:%03ld:"),
cur_time.wYear,
cur_time.wMonth,
cur_time.wDay,
cur_time.wHour,
cur_time.wMinute,
cur_time.wSecond,
cur_time.wMilliseconds);
if (fp != NULL)
{
switch (nType)
{
case Normal: strLog += _T("[NORMAL ] : "); break;
case Debug: strLog += _T("[DEBUG ] : "); break;
case End: strLog += _T("[End ] : "); break;
case Error: strLog += _T("[Error ] : "); break;
}
strLog += (CString)szLog;
fprintf(fp, "%s\r\n", (CStringA)strLog);
fflush(fp);
fclose(fp);
}
else
{
CString strErrorMsg;
DWORD dwErrNo = GetLastError();
strErrorMsg.Format(_T("LOG FILE Open Fail : Code = [ %d ], "), dwErrNo);
}
g_criticalLog.Unlock();
}
CString GetFilePath()
{
g_criticalExe.Lock();
static TCHAR pBuf[256] = { 0, };
memset(pBuf, NULL, sizeof(pBuf));
GetModuleFileName(NULL, pBuf, sizeof(pBuf));
CString strFilePath;
strFilePath.Format(_T("%s"), pBuf);
strFilePath = strFilePath.Left(strFilePath.ReverseFind(_T('\\')));
g_criticalExe.Unlock();
return strFilePath;
}
<사용 예>
Log(Normal, "프로그램이 정상적으로 작동 중입니다.");
Log(LogType::Normal, "프로그램이 정상적으로 작동 중입니다."); // LogType이 모호할 경우
'Development > MFC(Visual C++)' 카테고리의 다른 글
[MFC] 메모리 릭 체크하기 (0) | 2019.10.30 |
---|---|
[MFC] Onvif 프로토콜을 사용한 IP 카메라 출력하기 (2) | 2017.03.05 |
(C++) _T() 매크로를 사용하는 이유 (0) | 2016.12.26 |
[MFC] Invalidate (0) | 2016.08.09 |
[MFC] 파일의 내용 중 부분만 수정하여 쓰기 (1) | 2016.06.29 |