617 lines
15 KiB
C++
617 lines
15 KiB
C++
#include "StdAfx.h"
|
|
#include "TraceService.h" // #include "EventService.h"
|
|
#include <strsafe.h>
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//颜色定义
|
|
#define COLOR_TIME RGB(0,0,0)
|
|
#define COLOR_NORMAL RGB(125,125,125)
|
|
#define COLOR_WARN RGB(255,128,0)
|
|
#define COLOR_EXCEPTION RGB(200,0,0)
|
|
#define COLOR_DEBUG RGB(0,128,128)
|
|
|
|
#define IDM_MENU0 100
|
|
#define IDM_MENU1 110
|
|
#define IDM_MENU2 120
|
|
#define IDM_MENU3 130
|
|
#define IDM_MENU4 140
|
|
#define IDM_MENU5 150
|
|
|
|
#define TRACE_LEVEL_COUNT 5
|
|
//////////////////////////////////////////////////////////////////////////
|
|
struct tagTraceString
|
|
{
|
|
enTraceLevel enTL;
|
|
CString strMsg;
|
|
};
|
|
//追踪服务
|
|
//////////////////////////////////////////////////////////////////////////
|
|
static ITraceService *g_pITraceService = NULL;
|
|
static bool g_bEnableTrace=true;
|
|
static CWHArray<tagTraceString *> g_aryTraceString;
|
|
static CWHArray<tagTraceString *> g_aryTraceStringStorage;
|
|
static CCriticalSection g_CS;
|
|
//函数定义
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//构造函数
|
|
CTraceService::CTraceService()
|
|
{
|
|
|
|
}
|
|
|
|
//服务配置
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//设置服务
|
|
bool CTraceService::SetTraceService(IUnknownEx * pIUnknownEx)
|
|
{
|
|
g_pITraceService = QUERY_OBJECT_PTR_INTERFACE(pIUnknownEx, ITraceService);
|
|
return NULL != g_pITraceService;
|
|
}
|
|
|
|
//获取服务
|
|
VOID * CTraceService::GetTraceService(const IID & Guid, DWORD dwQueryVer)
|
|
{
|
|
ASSERT(g_pITraceService);
|
|
if (g_pITraceService) return NULL;
|
|
|
|
return (VOID*)g_pITraceService->QueryInterface(Guid, dwQueryVer);
|
|
}
|
|
|
|
//获取服务
|
|
VOID * CTraceService::GetTraceServiceManager(const IID & Guid, DWORD dwQueryVer)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
//状态管理
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//追踪状态
|
|
bool CTraceService::IsEnableTrace(enTraceLevel TraceLevel)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//追踪控制
|
|
bool CTraceService::EnableTrace(enTraceLevel TraceLevel, bool bEnableTrace)
|
|
{
|
|
return false;
|
|
}
|
|
//追踪控制
|
|
bool CTraceService::EnableAllTrace( bool bEnableTrace )
|
|
{
|
|
if (g_bEnableTrace!=bEnableTrace)
|
|
{
|
|
g_bEnableTrace=bEnableTrace;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
//功能函数
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//追踪信息
|
|
bool CTraceService::TraceString(LPCTSTR pszString, enTraceLevel TraceLevel)
|
|
{
|
|
if (g_pITraceService!=NULL && pszString!=NULL && *pszString!=0)
|
|
{
|
|
return g_pITraceService->TraceString(pszString, TraceLevel);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CTraceService::TraceFormat( enTraceLevel TraceLevel, LPCTSTR pszFormat,... )
|
|
{
|
|
if (g_bEnableTrace && g_pITraceService!=NULL && pszFormat!=NULL && *pszFormat!=0)
|
|
{
|
|
CString str;
|
|
va_list ptr;
|
|
va_start(ptr, pszFormat);
|
|
str.FormatV(pszFormat,ptr);
|
|
va_end(ptr);
|
|
return g_pITraceService->TraceString(str, TraceLevel);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//追踪服务
|
|
//////////////////////////////////////////////////////////////////////////
|
|
#define WM_TRACE_STRING WM_USER+1
|
|
|
|
BEGIN_MESSAGE_MAP(CTraceServiceControl, CRichEditCtrl)
|
|
ON_WM_RBUTTONDOWN()
|
|
ON_WM_CREATE()
|
|
ON_WM_DESTROY()
|
|
ON_MESSAGE(WM_TRACE_STRING,OnTraceServiceMessage)
|
|
ON_COMMAND(IDM_MENU0, OnCopyString)
|
|
ON_COMMAND(IDM_MENU1, OnSelectAll)
|
|
ON_COMMAND(IDM_MENU2, OnDeleteString)
|
|
ON_COMMAND(IDM_MENU3, OnClearAll)
|
|
ON_COMMAND(IDM_MENU4, OnSaveString)
|
|
END_MESSAGE_MAP()
|
|
|
|
//函数定义
|
|
|
|
//写入日志
|
|
void AutoSaveLog(CTraceServiceControl *pRichEditTrace)
|
|
{
|
|
static CString strLogPath;
|
|
if (strLogPath.IsEmpty())
|
|
{
|
|
TCHAR szBuf[MAX_PATH];
|
|
GetModuleFileName(NULL,szBuf,CountString(szBuf));
|
|
PathRemoveExtension(szBuf);
|
|
LPTSTR pszFileName=::PathFindFileName(szBuf);
|
|
CString strFileName(pszFileName);
|
|
StringCchCopy(pszFileName,CountString(szBuf)-(pszFileName-szBuf),_T("ServerLog"));
|
|
if (!::PathFileExists(szBuf))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (strFileName.CompareNoCase(_T("GameServer"))==0)
|
|
{
|
|
AfxGetMainWnd()->GetWindowText(strFileName);
|
|
strFileName.MakeLower();
|
|
strFileName.Replace(_T(".rop"),_T(""));
|
|
strFileName.Replace(_T("[加载成功]"),_T(""));
|
|
strFileName.Replace(_T("[加载失败]"),_T(""));
|
|
strFileName.Replace(_T("[停止]"),_T(""));
|
|
}
|
|
//获取时间
|
|
SYSTEMTIME st;
|
|
GetLocalTime(&st);
|
|
strLogPath.Format(_T("%s\\%s%04d%02d%02d%02d%02d%02d%03d.log"),szBuf,strFileName,
|
|
st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond,st.wMilliseconds);
|
|
}
|
|
try
|
|
{
|
|
CString strInput;
|
|
pRichEditTrace->GetWindowText(strInput);
|
|
if (!strInput.IsEmpty())
|
|
{
|
|
CFile file;
|
|
if (file.Open(strLogPath, CFile::modeCreate|CFile::modeWrite|CFile::typeBinary|CFile::modeNoTruncate))
|
|
{
|
|
file.SeekToEnd();
|
|
file.Write(strInput, strInput.GetLength()*sizeof(TCHAR));
|
|
file.Close();
|
|
}
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
ASSERT(0);
|
|
}
|
|
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//构造函数
|
|
CTraceServiceControl::CTraceServiceControl()
|
|
{
|
|
CTraceService::SetTraceService((IUnknownEx*)QueryInterface(IID_IUnknownEx, VER_IUnknownEx));
|
|
}
|
|
|
|
//析构函数
|
|
CTraceServiceControl::~CTraceServiceControl()
|
|
{
|
|
CTraceService::SetTraceService(NULL);
|
|
g_aryTraceStringStorage.Append(g_aryTraceString);
|
|
for ( INT_PTR i=g_aryTraceStringStorage.GetCount()-1; i>=0; i-- )
|
|
{
|
|
tagTraceString *pTraceString=g_aryTraceStringStorage[i];
|
|
SafeDelete(pTraceString);
|
|
}
|
|
}
|
|
|
|
//基础接口
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//接口查询
|
|
VOID * CTraceServiceControl::QueryInterface(const IID & Guid, DWORD dwQueryVer)
|
|
{
|
|
QUERYINTERFACE(ITraceService, Guid, dwQueryVer);
|
|
QUERYINTERFACE_IUNKNOWNEX(ITraceService, Guid, dwQueryVer);
|
|
return NULL;
|
|
}
|
|
|
|
//信息接口
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//追踪信息
|
|
bool CTraceServiceControl::TraceString(LPCTSTR pszString, enTraceLevel TraceLevel)
|
|
{
|
|
//效验参数
|
|
ITraceService *pITraceService = QUERY_ME_INTERFACE(ITraceService);
|
|
VERIFY_RETURN_FALSE(pITraceService != NULL);
|
|
//构造变量
|
|
tagTraceString *pTraceString=NULL;
|
|
g_CS.Lock();
|
|
INT_PTR iIndex=g_aryTraceStringStorage.GetCount()-1;
|
|
if (iIndex>=0)
|
|
{
|
|
pTraceString=g_aryTraceStringStorage[iIndex];
|
|
g_aryTraceStringStorage.RemoveAt(iIndex);
|
|
}
|
|
g_CS.Unlock();
|
|
|
|
if (NULL==pTraceString)
|
|
{
|
|
pTraceString=new tagTraceString;
|
|
}
|
|
VERIFY_RETURN_FALSE(pTraceString!=NULL);
|
|
//获取时间
|
|
SYSTEMTIME SystemTime;
|
|
GetLocalTime(&SystemTime);
|
|
//生成数据
|
|
pTraceString->enTL=TraceLevel;
|
|
pTraceString->strMsg.Format(TEXT("【 %04d-%02d-%02d %02d:%02d:%02d 】%s\n"), SystemTime.wYear, \
|
|
SystemTime.wMonth, SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond,pszString);
|
|
//添加到队列中
|
|
iIndex=-1;
|
|
g_CS.Lock();
|
|
iIndex=g_aryTraceString.Add(pTraceString);
|
|
g_CS.Unlock();
|
|
if (0==iIndex)
|
|
{
|
|
PostMessage(WM_TRACE_STRING,0,0);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//重载函数
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//绑定函数
|
|
VOID CTraceServiceControl::PreSubclassWindow()
|
|
{
|
|
__super::PreSubclassWindow();
|
|
CTraceService::SetTraceService((IUnknownEx*)QueryInterface(IID_IUnknownEx, VER_IUnknownEx));
|
|
}
|
|
|
|
//功能函数
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//加载消息
|
|
bool CTraceServiceControl::LoadMessage(LPCTSTR pszFileName)
|
|
{
|
|
if (static_cast<CTraceServiceControl*>(g_pITraceService) == NULL) return false;
|
|
return static_cast<CTraceServiceControl*>(g_pITraceService)->LoadMessage(pszFileName);
|
|
}
|
|
|
|
//保存信息
|
|
bool CTraceServiceControl::SaveMessage(LPCTSTR pszFileName)
|
|
{
|
|
if (static_cast<CTraceServiceControl*>(g_pITraceService) == NULL) return false;
|
|
return static_cast<CTraceServiceControl*>(g_pITraceService)->SaveMessage(pszFileName);
|
|
}
|
|
|
|
//设置参数
|
|
bool CTraceServiceControl::SetParameter(LONG lMaxLineCount, LONG lReserveLineCount)
|
|
{
|
|
m_lMaxLineCount = lMaxLineCount; //最大行数
|
|
m_lReserveLineCount = lReserveLineCount; //保留行数
|
|
|
|
return true;
|
|
}
|
|
|
|
//辅助函数
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//配置服务
|
|
VOID CTraceServiceControl::InitializeService()
|
|
{
|
|
|
|
}
|
|
|
|
//获取颜色
|
|
COLORREF CTraceServiceControl::GetTraceColor(enTraceLevel TraceLevel)
|
|
{
|
|
switch (TraceLevel)
|
|
{
|
|
case TraceLevel_Info : return RGB(15, 130, 248);
|
|
case TraceLevel_Normal : return RGB(133, 124, 129);
|
|
case TraceLevel_Warning : return RGB(232,100,27);
|
|
case TraceLevel_Exception : return RGB(255,0,0);
|
|
case TraceLevel_Debug : return RGB(19, 127, 140);
|
|
}
|
|
return RGB(0, 0, 0);
|
|
}
|
|
|
|
//字符判断
|
|
bool EfficacyUrlChar(TCHAR chChar)
|
|
{
|
|
//特殊字符
|
|
if (chChar == TEXT('.')) return true;
|
|
if (chChar == TEXT('=')) return true;
|
|
if (chChar == TEXT('+')) return true;
|
|
if (chChar == TEXT('?')) return true;
|
|
if (chChar == TEXT('#')) return true;
|
|
if (chChar == TEXT('%')) return true;
|
|
if (chChar == TEXT('/')) return true;
|
|
if (chChar == TEXT(':')) return true;
|
|
if (chChar == TEXT('&')) return true;
|
|
|
|
//字符范围
|
|
if ((chChar >= TEXT('a')) && (chChar <= TEXT('z'))) return true;
|
|
if ((chChar >= TEXT('A')) && (chChar <= TEXT('Z'))) return true;
|
|
if ((chChar >= TEXT('0')) && (chChar <= TEXT('9'))) return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
//地址判断
|
|
bool EfficacyUrlString(LPCTSTR pszUrl)
|
|
{
|
|
for (WORD i = 0; i < lstrlen(pszUrl); i++)
|
|
{
|
|
if (!EfficacyUrlChar(pszUrl[i])) return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//插入字串
|
|
bool CTraceServiceControl::InsertString(LPCTSTR pszString, CHARFORMAT2 & CharFormat)
|
|
{
|
|
if (GetTextLength() >= 0x80000)//1024 * 512
|
|
{
|
|
OnClearAll();
|
|
}
|
|
|
|
//插入消息
|
|
//变量定义
|
|
bool bResumeSelect;
|
|
CHARRANGE CharRange;
|
|
|
|
//保存状态
|
|
SetSel(-1L, -1L);
|
|
GetSel(CharRange.cpMin, CharRange.cpMax);
|
|
bResumeSelect = (CharRange.cpMax != CharRange.cpMin);
|
|
|
|
//搜索变量
|
|
LPCTSTR pszHttp = TEXT("http://");
|
|
const INT nHttpLength = lstrlen(pszHttp);
|
|
const INT nStringLength = lstrlen(pszString);
|
|
|
|
//索引定义
|
|
INT nStringStart = 0;
|
|
INT nStringPause = 0;
|
|
|
|
//字符解释
|
|
for (INT i = 0; i < nStringLength; i++)
|
|
{
|
|
//变量定义
|
|
INT nUrlPause = i;
|
|
|
|
//地址判断
|
|
if (((i + nHttpLength) < nStringLength) && (memcmp(&pszString[i], pszHttp, nHttpLength*sizeof(TCHAR)) == 0))
|
|
{
|
|
//设置索引
|
|
nUrlPause = i + nHttpLength;
|
|
|
|
//地址搜索
|
|
while (nUrlPause < nStringLength)
|
|
{
|
|
//字符判断
|
|
if (EfficacyUrlChar(pszString[nUrlPause]))
|
|
{
|
|
nUrlPause++;
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
//终止字符
|
|
if (nUrlPause <= (i + nHttpLength)) nStringPause = (i + 1);
|
|
|
|
//插入字符
|
|
if ((i == (nStringLength - 1)) || (nUrlPause > (i + nHttpLength)))
|
|
{
|
|
//普通字符
|
|
if (nStringPause > nStringStart)
|
|
{
|
|
//获取缓冲
|
|
CString strNormalString;
|
|
LPTSTR pszNormalString = strNormalString.GetBuffer(nStringPause - nStringStart + 1);
|
|
|
|
//拷贝字符
|
|
pszNormalString[nStringPause-nStringStart] = 0;
|
|
CopyMemory(pszNormalString, &pszString[nStringStart], (nStringPause - nStringStart)*sizeof(TCHAR));
|
|
|
|
//释放缓冲
|
|
strNormalString.ReleaseBuffer();
|
|
|
|
//插入消息
|
|
SetSel(-1L, -1L);
|
|
SetWordCharFormat(CharFormat);
|
|
ReplaceSel((LPCTSTR)strNormalString);
|
|
}
|
|
|
|
//连接地址
|
|
if (nUrlPause > (i + nHttpLength))
|
|
{
|
|
//获取缓冲
|
|
CString strUrlString;
|
|
LPTSTR pszUrlString = strUrlString.GetBuffer((nUrlPause - i) + 1);
|
|
|
|
//拷贝字符
|
|
pszUrlString[nUrlPause-i] = 0;
|
|
CopyMemory(pszUrlString, &pszString[i], (nUrlPause - i)*sizeof(TCHAR));
|
|
|
|
//释放缓冲
|
|
strUrlString.ReleaseBuffer();
|
|
|
|
//构造格式
|
|
CHARFORMAT2 CharFormatHyper;
|
|
CharFormatHyper = CharFormat;
|
|
|
|
//效验地址
|
|
if (EfficacyUrlString(strUrlString))
|
|
{
|
|
CharFormatHyper.dwMask |= CFM_LINK;
|
|
CharFormatHyper.dwEffects |= CFE_LINK;
|
|
}
|
|
|
|
//插入消息
|
|
SetSel(-1L, -1L);
|
|
SetWordCharFormat(CharFormatHyper);
|
|
ReplaceSel((LPCTSTR)strUrlString);
|
|
}
|
|
|
|
//设置索引
|
|
nStringStart = __max(i, nUrlPause);
|
|
}
|
|
|
|
//设置索引
|
|
i += (nUrlPause - i);
|
|
}
|
|
|
|
//状态设置
|
|
if (bResumeSelect)
|
|
{
|
|
SetSel(CharRange);
|
|
}
|
|
else
|
|
{
|
|
PostMessage(WM_VSCROLL, SB_BOTTOM, 0);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//回调函数
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//加载回调
|
|
DWORD CALLBACK CTraceServiceControl::LoadCallBack(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
//保存回调
|
|
DWORD CALLBACK CTraceServiceControl::SaveCallBack(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
//菜单命令
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//删除信息
|
|
VOID CTraceServiceControl::OnClearAll()
|
|
{
|
|
AutoSaveLog(this);
|
|
SetWindowText(NULL);
|
|
}
|
|
|
|
//全部选择
|
|
VOID CTraceServiceControl::OnSelectAll()
|
|
{
|
|
__super::SetSel(0, __super::GetTextLength());
|
|
}
|
|
|
|
//拷贝字符
|
|
VOID CTraceServiceControl::OnCopyString()
|
|
{
|
|
__super::Copy();
|
|
}
|
|
|
|
//保存信息
|
|
VOID CTraceServiceControl::OnSaveString()
|
|
{
|
|
CFileDialog dlg(FALSE, _T("*.txt"), NULL, 4 | 2, _T("信息|*.txt||"));
|
|
if (dlg.DoModal() == IDOK)
|
|
{
|
|
CFile file;
|
|
if (file.Open(dlg.GetPathName(), CFile::modeCreate | CFile::modeWrite))
|
|
{
|
|
CString strInput;
|
|
GetWindowText(strInput);
|
|
file.Write(strInput, strInput.GetLength());
|
|
file.Close();
|
|
}
|
|
}
|
|
}
|
|
|
|
//删除字符
|
|
VOID CTraceServiceControl::OnDeleteString()
|
|
{
|
|
ReplaceSel(NULL, true);
|
|
}
|
|
|
|
//消息映射
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//建立消息
|
|
INT CTraceServiceControl::OnCreate(LPCREATESTRUCT lpCreateStruct)
|
|
{
|
|
if (__super::OnCreate(lpCreateStruct)==-1)
|
|
{
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//右键消息
|
|
VOID CTraceServiceControl::OnRButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
CMenu menu;
|
|
ClientToScreen(&point);
|
|
|
|
menu.CreatePopupMenu();
|
|
|
|
CHARRANGE sl;
|
|
GetSel(sl);
|
|
menu.AppendMenu(MF_STRING | (sl.cpMax != sl.cpMin) ? 0 : MF_DISABLED | MF_GRAYED, IDM_MENU0, _T("复制(&C)\tCtrl+C"));
|
|
menu.AppendMenu(MF_STRING | (GetTextLength() > 0 && sl.cpMax - sl.cpMin < GetTextLength()) ? 0 : MF_DISABLED | MF_GRAYED, IDM_MENU1, _T("全选(&A)\tCtrl+A"));
|
|
menu.AppendMenu(MF_STRING | (false) ? 0 : MF_DISABLED | MF_GRAYED, IDM_MENU2, _T("删除(&D)"));
|
|
menu.AppendMenu(MF_STRING | (GetTextLength() > 0) ? 0 : MF_DISABLED | MF_GRAYED, IDM_MENU3, _T("清除信息"));
|
|
menu.AppendMenu(MF_SEPARATOR, 0);
|
|
menu.AppendMenu(MF_STRING | (GetTextLength() > 0) ? 0 : MF_DISABLED | MF_GRAYED, IDM_MENU4, _T("保存信息..."));
|
|
|
|
TrackPopupMenu(menu.m_hMenu, nFlags, point.x, point.y, 0, m_hWnd, NULL);
|
|
}
|
|
|
|
//追踪消息
|
|
LRESULT CTraceServiceControl::OnTraceServiceMessage(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (g_aryTraceString.IsEmpty())
|
|
{
|
|
return 0;
|
|
}
|
|
CWHArray<tagTraceString *> ary;
|
|
//获取当前追踪信息
|
|
g_CS.Lock();
|
|
ary.Append(g_aryTraceString);
|
|
g_aryTraceString.RemoveAll();
|
|
g_CS.Unlock();
|
|
|
|
//输出信息
|
|
|
|
//变量定义
|
|
CHARFORMAT2 CharFormat;
|
|
ZeroMemory(&CharFormat, sizeof(CharFormat));
|
|
|
|
//构造数据
|
|
CharFormat.cbSize = sizeof(CharFormat);
|
|
CharFormat.dwMask = CFM_COLOR | CFM_BACKCOLOR;
|
|
CharFormat.crTextColor = RGB(0, 0, 0);
|
|
CharFormat.crBackColor = RGB(255, 255, 255);
|
|
|
|
StringCchCopy(CharFormat.szFaceName, CountString(CharFormat.szFaceName), TEXT("宋体"));
|
|
|
|
for ( INT_PTR i=0,n=ary.GetCount(); i<n; i++ )
|
|
{
|
|
tagTraceString *pTraceString=ary[i];
|
|
CharFormat.crTextColor = GetTraceColor(pTraceString->enTL);
|
|
InsertString(pTraceString->strMsg, CharFormat);
|
|
}
|
|
|
|
//内存回收
|
|
g_CS.Lock();
|
|
g_aryTraceStringStorage.Append(ary);
|
|
g_CS.Unlock();
|
|
return 0;
|
|
}
|
|
|
|
void CTraceServiceControl::OnDestroy()
|
|
{
|
|
AutoSaveLog(this);
|
|
return __super::OnDestroy();
|
|
}
|