これまで書き溜めてきたソースコードの中から流用できそうなものを見繕ってアップしていこうと思っています。
よろしくお願いします。早速ですが・・・
●ログ出力クラス
Compiler : Visual Stadio/C++
使い方 :
LogManager.h LogManager.cpp をプロジェクトに追加してログ出力を行いたいソースで LogManager.h をインクルードし、
以下のマクロを使用して出力してください。
LOG_DEBUG 文字列を出力 デバッグコンパイル時のみ出力される
LOGF_DEBUG 書式付き出力(printfに準ずる)デバッグコンパイル時のみ出力される
LOG_ERROR 文字列を出力
LOGF_ERROR 書式付き出力(printfに準ずる)
注意点:
1.ログ編集用バッファのサイズは 200文字にしています。 200文字を超えると例外またはアサーションエラーが発生します。
これより長い文字数が必要な場合は LogManager.h の LOG_BUFSIZE マクロを変更してください。
2.ログファイルはカレントディレクトリに debug.log の名前で作成されます。
別のパスにしたい場合は LogManager.h の LOG_FILEPATH マクロを変更してください。
3.別々のプロセスから同時に同じログファイルに出力するような使い方には対応していません。
使用条件
コピー・流用・改変等、一切制限しません。
LogManager.h
// ログ出力クラスヘッダー
#pragma once
#include <Windows.h>
#include <tchar.h>
#define LOG_BUFSIZE (200)
#define LOG_FILEPATH (_T(".\\debug.log"))
class CLogManager
{
protected:
HANDLE m_hLogFile; // ログファイルハンドル
CRITICAL_SECTION m_cs; // クリティカルセクション
public:
CLogManager();
virtual ~CLogManager();
// ログ出力
DWORD PrintLog(LPCTSTR sText);
// 書式付きログ出力
DWORD PrintLogF(LPCTSTR sFormat, ...);
// トレースログ出力
DWORD PrintTraceLog(LPCTSTR sFile, int nLine, LPCTSTR sText);
// 書式付きトレースログ出力
DWORD PrintTraceLogF(LPCTSTR sFile, int nLine, LPCTSTR sFormat, ...);
};
// 作成済みCLogManagerオブジェクト
extern CLogManager LogMng;
// ログ出力マクロ
#if defined(_DEBUG) || defined(DEBUG)
#define LOG_DEBUG(a) LogMng.PrintTraceLog(_T(__FILE__), __LINE__, (a))
#define LOGF_DEBUG(fmt, ...) LogMng.PrintTraceLogF(_T(__FILE__), __LINE__, fmt, __VA_ARGS__)
#else
#define LOG_DEBUG(a)
#define LOGF_DEBUG(fmt, ...)
#endif
#define LOG_ERROR(a) LogMng.PrintLog((a))
#define LOGF_ERROR(fmt, ...) LogMng.PrintLogF(fmt, __VA_ARGS__)
// ログ出力クラス実装
#include "stdafx.h"
#include "LogManager.h"
#include <stdarg.h>
CLogManager::CLogManager()
{
InitializeCriticalSection(&m_cs);
m_hLogFile = CreateFile(LOG_FILEPATH, GENERIC_WRITE, FILE_SHARE_READ,
NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (m_hLogFile == INVALID_HANDLE_VALUE)
{
return ;
}
#ifdef _UNICODE
if (GetLastError() != ERROR_ALREADY_EXISTS)
{
char BOM[2] = { (char)0xff, (char)0xfe };
DWORD dwLen;
WriteFile(m_hLogFile, BOM, 2, &dwLen, NULL);
}
#endif // _UNICODE
SetFilePointer(m_hLogFile, 0, 0, FILE_END);
}
CLogManager::~CLogManager()
{
if (m_hLogFile != INVALID_HANDLE_VALUE)
{
FlushFileBuffers(m_hLogFile);
CloseHandle(m_hLogFile);
}
DeleteCriticalSection(&m_cs);
}
DWORD CLogManager::PrintLog(LPCTSTR sText)
{
return PrintLogF(sText);
}
DWORD CLogManager::PrintLogF(LPCTSTR sFormat, ...)
{
EnterCriticalSection(&m_cs);
if (m_hLogFile == INVALID_HANDLE_VALUE)
{
LeaveCriticalSection(&m_cs);
return 0;
}
LPTSTR *pParam = ((LPTSTR*)&sFormat) + 1;
DWORD nLen = 0L;
SYSTEMTIME stime;
GetLocalTime(&stime);
LPTSTR sFormatLineBuff = new TCHAR[LOG_BUFSIZE];
LPTSTR sLineBuff = new TCHAR[LOG_BUFSIZE];
_vstprintf_s(sFormatLineBuff, LOG_BUFSIZE, sFormat, (va_list)pParam);
_stprintf_s(sLineBuff, LOG_BUFSIZE, _T("%04d/%02d/%02d %02d:%02d:%02d.%03d %s\r\n")
, stime.wYear, stime.wMonth, stime.wDay
, stime.wHour, stime.wMinute, stime.wSecond, stime.wMilliseconds
, sFormatLineBuff);
WriteFile(m_hLogFile, sLineBuff, _tcslen(sLineBuff)*sizeof(TCHAR), &nLen, NULL);
delete[] sFormatLineBuff;
delete[] sLineBuff;
LeaveCriticalSection(&m_cs);
return nLen;
}
DWORD CLogManager::PrintTraceLog(LPCTSTR sFile, int nLine, LPCTSTR sText)
{
if (m_hLogFile == INVALID_HANDLE_VALUE)
{
return 0;
}
LPCTSTR pos;
if ((pos = _tcsrchr(sFile, _T('\\'))) != NULL)
{
pos++;
}
else if ((pos = _tcsrchr(sFile, _T(':'))) != NULL)
{
pos++;
}
else
{
pos = sFile;
}
return PrintLogF(_T("[%s:%d] %s"), pos, nLine, sText);
}
DWORD CLogManager::PrintTraceLogF(LPCTSTR sFile, int nLine, LPCTSTR sFormat, ...)
{
if (m_hLogFile == INVALID_HANDLE_VALUE)
{
return 0;
}
LPCTSTR pos;
if ((pos = _tcsrchr(sFile, _T('\\'))) != NULL)
{
pos++;
}
else if ((pos = _tcsrchr(sFile, _T(':'))) != NULL)
{
pos++;
}
else
{
pos = sFile;
}
LPTSTR sLog = new TCHAR[LOG_BUFSIZE];
va_list argptr;
va_start(argptr, sFormat);
_vstprintf_s(sLog, LOG_BUFSIZE, sFormat, argptr);
DWORD dwRes = PrintLogF(_T("[%s:%d] %s"), pos, nLine, sLog);
delete[] sLog;
return dwRes;
}
CLogManager LogMng;