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