信息输出类
在写程序的时候如果不想中断代码的运行(多线程调试困难就在于此,你F9中断会影响其他线程)就需要输出信息,TRACE可以输出OutputDebugString也可以输出但终究感觉不爽,于是写了这个类,有了这个类,你可以很方便的输出信息到控制台窗口、文件、调试窗口、邮槽等等,你还可以采用其他方式输出,希望它能让你结束调试的痛苦。
///////////////////////////////////////////H///////////////////////////////////////////////////////////
#ifndef LGLIB_DEBUG_H
#define LGLIB_DEBUG_H
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <stdio.h>
#include "Lg_SyncLock.h"
#define DYNA_STRING 2048
#define MAX_PATH 260
#define _countof(array) (sizeof(array)/sizeof(array[0]))
namespace lglib
{
typedef enum _OUTPUTTYPE
{
Output_Console = 0,
Output_Trace,
Output_File,
Output_Mailslot
}OutputType;
/************************************************************************/
/* 调试信息输出类,象上面枚举所描述的那样通过这个类你可以有四类输出
/* 1,控制台输出,2,Output窗口输出,3,输出到文件,4,输出到邮槽
/* 至于其他输出类型你可以自行添加
/************************************************************************/
class __LGLIB__ lg_Debug
{
public:
lg_Debug(BOOL isconsole = TRUE,BOOL ismailslot = FALSE);
virtual ~lg_Debug();
public: //define
public: //var
void SetDebugFilePath(const char * filepath = NULL);
BOOL SetDebugMailslot(const char * mailslot);
void SetDebugColor(uint16 ForeColor = (/*FOREGROUND_RED | */FOREGROUND_GREEN | FOREGROUND_BLUE|FOREGROUND_INTENSITY) ,uint16 BackGroundColor = 0);
BOOL outdebug(OutputType type,const char* lpFormat,...);
private:
void StartConsoleWin(int16 width, int16 height);
BOOL SaveDataToFile(const char* data,const long DataLen);
BOOL SendMailslot(const char* data);
private:
HANDLE m_hStdOut;
BOOL m_bIsConsole;
BOOL m_bIsMailslot;
BOOL m_bIsFirstIn;
char m_chBuffer[DYNA_STRING];
char m_chFilePath[MAX_PATH];
char m_chMailslot[MAX_PATH];
//互斥为了保证多线程访问的同步
lg_Mutex m_mutex;
};
extern lg_Debug _LGDEBUG;
}
#define LGTRACE _LGDEBUG.outdebug
//由于要捕获行号和文件名,所以只能用宏定义了
//如果不需要行号和文件名的话,在异常类的构造部分输出即可
//开始捕获异常
#define LGTRY try {
//捕获自定义异常
#define OWCATCH \
}catch(const lg_Exception & e){ \
LGTRACE(Output_File, \
"<异常!!----------------------------------\r\n" \
"\tMethod = %s\r\n" \
"\tMessage = %s\r\n" \
"\tfile = %s\r\n" \
"\tline = %u\r\n" \
"----------------------------------异常!!>\r\n", \
e.getMethod().c_str(),e.getMessage().c_str(),__FILE__,__LINE__ );
//捕获其他异常
#define PBCATCH \
}catch(...){
//异常体结束
#define ENDCATCH }
#endif // LGLIB_DEBUG_H
///////////////////////////////////////////////CPP////////////////////////////////////////////////////
#include "stdafx.h"
#include "lg_Debug.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
namespace lglib
{
lg_Debug _LGDEBUG;
lg_Debug::lg_Debug(BOOL isconsole,BOOL ismailslot)
: m_hStdOut(NULL) ,m_bIsFirstIn(TRUE),
m_bIsConsole(isconsole) , m_bIsMailslot(ismailslot)
{
memset(m_chBuffer,0,DYNA_STRING);
memset(m_chFilePath,0,MAX_PATH);
memset(m_chMailslot,0,MAX_PATH);
StartConsoleWin(800,600);
SetDebugColor();
}
lg_Debug::~lg_Debug()
{
}
void lg_Debug::SetDebugFilePath(const char * filepath)
{
if(filepath == NULL)
strcpy(m_chFilePath,"d:\\debuginfo.txt");
else
strcpy(m_chFilePath,filepath);
}
BOOL lg_Debug::SetDebugMailslot(const char * mailslot)
{
if(!m_bIsMailslot || NULL == mailslot)
return FALSE;
strcpy(m_chMailslot,mailslot);
return TRUE;
}
void lg_Debug::SetDebugColor(unsigned short ForeColor,unsigned short BackGroundColor)
{
SetConsoleTextAttribute(m_hStdOut,ForeColor|BackGroundColor);
}
BOOL lg_Debug::outdebug(OutputType type,const char* lpFormat,...)
{
BOOL Ret = FALSE;
m_mutex.lock();
va_list args;
va_start(args, lpFormat);
_vsnprintf(m_chBuffer, _countof(m_chBuffer), lpFormat, args);
va_end(args);
strcat(m_chBuffer,"\r\n");
switch(type){
case Output_Console:
{
DWORD cCharsWritten;
Ret = WriteConsole(m_hStdOut, m_chBuffer, strlen(m_chBuffer), &cCharsWritten, NULL);
}
break;
case Output_Trace:
{
OutputDebugStr(m_chBuffer);
Ret = TRUE;
}
break;
case Output_File:
{
Ret = SaveDataToFile(m_chBuffer,strlen(m_chBuffer));
}
break;
case Output_Mailslot:
{
if(m_bIsMailslot)
Ret = SendMailslot(m_chMailslot);
else
Ret = FALSE;
}
break;
}
m_mutex.unlock();
return Ret;
}
void lg_Debug::StartConsoleWin(int16 width, int16 height)
{
AllocConsole();//分配
SetConsoleTitle("Debug Window");
m_hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);//指明句柄为标准输出HANDLE
COORD co = {width,height};
SetConsoleScreenBufferSize(m_hStdOut, co);//指明缓冲区大小
}
BOOL lg_Debug::SaveDataToFile(const char* data,const long DataLen)
{
DWORD numtowrite = 0;
HANDLE hFile = CreateFile(m_chFilePath,
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
m_bIsFirstIn?CREATE_ALWAYS:OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(m_bIsFirstIn)
m_bIsFirstIn = !m_bIsFirstIn;
if(INVALID_HANDLE_VALUE == hFile){
return FALSE;
}
if(0xFFFFFFFF == SetFilePointer(hFile,0,0,FILE_END)){
CloseHandle(hFile);
return FALSE;
}
if(FALSE == WriteFile(hFile,data,DataLen,&numtowrite,NULL)){
CloseHandle(hFile);
return FALSE;
}
if(FALSE == CloseHandle(hFile))
return FALSE;
return TRUE;
}
BOOL lg_Debug::SendMailslot(const char* data)
{
DWORD cbWritten;
HANDLE hFile = CreateFile(m_chMailslot,
GENERIC_WRITE,
FILE_SHARE_READ,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
if (hFile == INVALID_HANDLE_VALUE)
return FALSE;
if(FALSE == WriteFile(hFile, data,(DWORD)lstrlen(data),&cbWritten,(LPOVERLAPPED) NULL)){
::CloseHandle(hFile);
return FALSE;
}
if(FALSE == ::CloseHandle(hFile))
return FALSE;
return TRUE;
}
}