Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1852054
  • 博文数量: 909
  • 博客积分: 4000
  • 博客等级: 上校
  • 技术积分: 12260
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-06 20:50
文章分类

全部博文(909)

文章存档

2008年(909)

我的朋友

分类:

2008-05-06 21:45:43

一起学习
利用XML文件写日志的类
作者:战鹰

下载本文示例工程

对于程序执行期间的错误跟踪!相信大家都有自己的一套办法!!!但都是利用文件文件,我这次利用的是XML&XSL,可产生报表格式的日志,轻松生成报表!!!

我参考了Emilio Guijarro Cameros的CXMLProfile写XML配置文件的思想!!!利用XML 接口IXMLDOMDocument 、IXMLDOMNode 、IXMLDOMElement和 MFC相结合,写成了一个CXMLLogfile类,只暴露了两个公共方法

void Log(LPCTSTR lpszFilName,LPCTSTR s,...);

bool ClearAll()

Log是添加一条日志,ClearAll是清除所有日志!!!当大家需要查看日值时,只需要打开相应的XML文件Log.XML就可以看到一个日志表格了,为此我专门写了一个XSL样式文件(XML样式XSL文件必须在XML文件同一目录下)!
XSL样式文件代码:










 

  <xsl:value-of select="LogFile/AppName" /> 日志文件

 

 

  

运行日志文件

日期-时间 错误信息 具体位置信息
.

Log.xsl by force eagle <force_eagle@163.net>
以下是一日志表格图:


以下是源代码,需要IE5.5以上支持!!!如果编译错误!请下载微软的最新XML SDK!!!!
// XMLLogfile.h: interface for the CXMLLogfile class.

//

//////////////////////////////////////////////////////////////////////



#if !defined(AFX_XMLLOGFILE_H__EA8ACC84_7139_49F6_9B8A_F69D9CF5C385__INCLUDED_)

#define AFX_XMLLOGFILE_H__EA8ACC84_7139_49F6_9B8A_F69D9CF5C385__INCLUDED_



#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

#include 

#include 

#include 

#include 

#include 

#include 

//Author : By force eagle

//Date time : 2003-5-26 17:08

//reference : 

//				CXMLProfile By Emilio Guijarro Cameros 

//				Christian Richardt



#pragma comment(lib,"msxml2.lib")

class CXMLLogfile : public CObject  

{

	CString m_strFileName;

	IXMLDOMDocument *m_pXMLDoc;

	

	IXMLDOMNode * GetChildNode(LPCTSTR lpszParent, LPCTSTR lpszChild,BOOL bCreate = TRUE);

	IXMLDOMNode * GetFirstLevelNode(LPCTSTR lpszNodeName,BOOL bCreate = TRUE);



	// UNIX timestamp: seconds from 1970-01-01 00:00:00 (UTC)

	inline double TimeStamp(void)

	{

		_timeb ts;

		_ftime( &ts );

		return (int)ts.time   (ts.millitm/1000.0);

	};

protected:

	void AppendNode(IXMLDOMNode * pXMLItem, LPCTSTR lpszNodeName, LPCTSTR lpszValue);

	void AppendItem(LPCTSTR lpszFileName,LPCTSTR lpszComment);



	void Flush();



	bool CreateLogFile(LPCTSTR lpszLogFilName);



	void DumpComError(_com_error &e);



	void Init();





public:

	CXMLLogfile(LPCTSTR lpszFileName = NULL);

	virtual ~CXMLLogfile();

	void Log(LPCTSTR lpszFilName,LPCTSTR s,...);

	bool ClearAll();

};



#endif // !defined(AFX_XMLLOGFILE_H__EA8ACC84_7139_49F6_9B8A_F69D9CF5C385__INCLUDED_)

// XMLLogfile.cpp: implementation of the CXMLLogfile class.

//

//////////////////////////////////////////////////////////////////////



#include "stdafx.h"

#include "XMLLogfile.h"



#ifdef _DEBUG

#undef THIS_FILE

static char THIS_FILE[]=__FILE__;

#define new DEBUG_NEW

#endif



//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

/*

static TCHAR *szLogOrig= {_T("\n"

	"\n"

	"\nXXXX\n1053925276.381\n"

	"2003-05-26\n\n\n")};

//*/

static WCHAR *wszLogOrig = {L"\n\

\n\

\nXXXX\n\

1053925276.381\n\

2003-05-26\n\

\n\n"};



CXMLLogfile::CXMLLogfile(LPCTSTR lpszFileName)

{

	VARIANT_BOOL bResult;

	IXMLDOMElement *pRootNode;

	HRESULT hr;

	if (NULL == lpszFileName)

	{

		CString strHlpPath ,strAppName;

		strHlpPath = AfxGetApp()->m_pszHelpFilePath;

		strAppName = AfxGetAppName();

		strHlpPath = strHlpPath.Left(strHlpPath.GetLength() - 4

			- strAppName.GetLength());

		m_strFileName = strHlpPath   _T("LOG.XML");

	}

	else

	{

		m_strFileName = lpszFileName;

	}



	hr = CoInitialize(NULL); 

LoadLog:

	if(SUCCEEDED(hr)) 

	{

		hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, 

			IID_IXMLDOMDocument, (void**)&m_pXMLDoc);

		if(SUCCEEDED(hr)) 

		{

			m_pXMLDoc->load(COleVariant(m_strFileName), &bResult);

		}

	}



	//取得根节点

	m_pXMLDoc->get_documentElement(&pRootNode);



	if(pRootNode == NULL)	//无根节点

	{

		m_pXMLDoc->Release();

		m_pXMLDoc = NULL;

		//重新创建XML日值文件

		CreateLogFile(m_strFileName);

		goto LoadLog; //重新载入

	}

	else

	{

		Init();

	}

}



CXMLLogfile::~CXMLLogfile()

{

	m_pXMLDoc->save(COleVariant(m_strFileName));

	m_pXMLDoc->Release();

}

/*

*	函数名称:	Init()

*	说明:		初始化XML日志文件的工程信息

*	参数:	

*			无

*	返回:	无

*/

void CXMLLogfile::Init()

{

	IXMLDOMNode *pAppNameNode, *pTimestamp, *pDate, *pTime;;

	TCHAR        *szTemp = new TCHAR[MAX_PATH];

	HRESULT hr ;



	CTime	timeCur ;

	timeCur = CTime::GetCurrentTime();

	CString strDate, strTime;

	strDate = timeCur.Format(_T("%Y-%m-%d"));

	strTime = timeCur.Format(_T("%X"));



	//更改工程名称

	pAppNameNode = GetFirstLevelNode(_T("AppName"));

	hr = pAppNameNode->put_text(CComBSTR(AfxGetAppName()));

	pAppNameNode->Release();

//*	

	//时间戳

	ZeroMemory(szTemp,MAX_PATH);

	double timestamp = TimeStamp();

	_stprintf(szTemp,_T("%.3f"),timestamp);

	pTimestamp = GetFirstLevelNode(_T("Timestamp"));

	hr = pTimestamp->put_text(CComBSTR(szTemp));

	pTimestamp->Release();

//*/

	//日期

	pDate = GetFirstLevelNode(_T("Date"));

	hr = pDate->put_text(CComBSTR(strDate));

	pDate->Release();	



	//时间

	pTime = GetFirstLevelNode(_T("Time"));

	hr = pTime->put_text(CComBSTR(strTime));

	pTime->Release();



	delete szTemp;

	Flush();

}

/*

*	函数名称:	DumpComError(_com_error &e)

*	说明:		输出COM错误信息

*	参数:	

*			IN  _com_error &e	COM错误信息对象

*	返回:	无

*/

void CXMLLogfile::DumpComError(_com_error &e)

{

	_bstr_t bstrSource(e.Source());

	_bstr_t bstrDescription(e.Description());

	

	TRACE("Error\n");

	TRACE("\tCode = lx\n", e.Error());

	TRACE("\tCode meaning = %s\n", e.ErrorMessage());

	TRACE("\tSource = %s\n", (LPCSTR) bstrSource);

	TRACE("\tDescription = %s\n", (LPCSTR) bstrDescription);

}

/*

*	函数名称:	CreateLogFile(LPCTSTR lpszLogFilName)

*	说明:		创建原始的XML日志文件

*	参数:	

*			IN  LPCTSTR lpszLogFileName 文件名称

*	返回:	true 成功

*/

bool CXMLLogfile::CreateLogFile(LPCTSTR lpszLogFilName)

{

	IXMLDOMDocument *pXMLDoc = NULL;



	BSTR	bstr = NULL;

	VARIANT_BOOL	status;

	HRESULT hr;



	try

	{

		hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, 

			IID_IXMLDOMDocument, (void**)&pXMLDoc);



		if (FAILED(hr))

			_com_issue_error(hr);



		bstr = ::SysAllocString(wszLogOrig);

		ASSERT(NULL != bstr);

		hr = pXMLDoc->loadXML(bstr,&status);

		::SysFreeString(bstr);



		if (FAILED(hr))

			_com_issue_error(hr);



		if(status != VARIANT_TRUE)

		{

			return false;

		}



		hr = pXMLDoc->save(COleVariant(lpszLogFilName));

		if (FAILED(hr))

			_com_issue_error(hr);



		pXMLDoc->Release();

	}

	catch(_com_error &e)

	{

		DumpComError(e);

		return false;

	}

	return true;

}

/*

*	函数名称:	GetFirstLevelNode(LPCTSTR lpszNodeName)

*	说明:		根据名称查找第一层子节点指针,没有则判断是否创建

*	参数:	

*			IN  LPCTSTR lpszNodeName 节点名称

*			IN  BOOL	bCreate 是否创建

*	返回:	IXMLDOMNode *	节点指针

*/

IXMLDOMNode * CXMLLogfile::GetFirstLevelNode(LPCTSTR lpszNodeName,BOOL bCreate)

{

	IXMLDOMElement *pRootNode = NULL, *element = NULL;

	IXMLDOMNode    *pLogItem = NULL, *pResultNode = NULL;

	CComBSTR       szName;

	bool           bSecFound = false, bEntryFound = false;

//	wchar_t        *szTemp = new wchar_t[255];



	m_pXMLDoc->get_documentElement(&pRootNode);

	

	for(pRootNode->get_firstChild(&pLogItem); pLogItem != NULL; pLogItem->get_nextSibling(&pLogItem)) 

	{

		pLogItem->get_baseName(&szName);



		if(szName == CComBSTR(lpszNodeName)) 

		{

			pResultNode = pLogItem;

			break;

		}

	}



	if(pLogItem == NULL && bCreate) 

	{

		m_pXMLDoc->createElement(CComBSTR(lpszNodeName), &element);

		pRootNode->appendChild(element, &pLogItem);

		element->Release();

		pResultNode = pLogItem;

	}



	pRootNode->Release();

	

	return pResultNode;

}

/*

*	函数名称:	GetChildNode(LPCTSTR lpszParent, LPCTSTR lpszChild)

*	说明:		查找父节点下的某一子节点指针,没有则判断是否创建创建

*	参数:	

*			IN  LPCTSTR lpszParent 父节点名称

*			IN	LPCTSTR lpszChild	子节点名称

*			IN  BOOL	bCreate    是否创建

*	返回:	IXMLDOMNode *	子节点指针

*/

IXMLDOMNode * CXMLLogfile::GetChildNode(LPCTSTR lpszParent, LPCTSTR lpszChild,BOOL bCreate)

{

	IXMLDOMElement *pRootNode= NULL, *element= NULL;

	IXMLDOMNode    *pLogItem= NULL, *pLogData= NULL, *pResultNode= NULL;

	CComBSTR       szName;



	m_pXMLDoc->get_documentElement(&pRootNode);

	

	for(pRootNode->get_firstChild(&pLogItem); pLogItem != NULL; pLogItem->get_nextSibling(&pLogItem)) 

	{

		pLogItem->get_baseName(&szName);



		if(szName == CComBSTR(lpszParent)) 

		{

			for(pLogItem->get_firstChild(&pLogData); pLogData != NULL; pLogData->get_nextSibling(&pLogData)) 

			{

				pLogData->get_baseName(&szName);



				if(szName == CComBSTR(lpszChild)) 

				{

					pResultNode = pLogData;				

					break;

				}

			}



			if(pLogData == NULL && bCreate) 

			{

				m_pXMLDoc->createElement(CComBSTR(lpszChild), &element);

				pLogItem->appendChild(element, &pLogData);

				element->Release();

				pResultNode = pLogData;

			}

			pLogItem->Release();

			break;

		}

	}



	if(pLogItem == NULL && bCreate) 

	{

		m_pXMLDoc->createElement(CComBSTR(lpszParent), &element);

		pRootNode->appendChild(element, &pLogItem);

		element->Release();

		m_pXMLDoc->createElement(CComBSTR(lpszChild), &element);

		pLogItem->appendChild(element, &pLogData);

		element->Release();

		pResultNode = pLogData;

	}

	

	pRootNode->Release();



	return pResultNode;

}

/*

*	函数名称:	AppendNode(IXMLDOMNode * pXMLItem, LPCTSTR lpszNodeName, LPCTSTR lpszValue)

*	说明:		在XML中添加一节点,并赋值为 lpszValue

*	参数:	

*			IN  IXMLDOMNode *	pXMLItem 要添加节点的节点指针

*			IN	LPCTSTR lpszNodeName	添加的节点名称

*			IN  LPCTSTR lpszComment		值

*/

void CXMLLogfile::AppendNode(IXMLDOMNode * pXMLItem, LPCTSTR lpszNodeName, LPCTSTR lpszValue)

{

	IXMLDOMElement *element;

	IXMLDOMNode *pLogData;



	m_pXMLDoc->createElement(CComBSTR(lpszNodeName),&element);

	pXMLItem->appendChild(element,&pLogData);

	element->Release();



	pLogData->put_text(CComBSTR(lpszValue));

	pLogData->Release();	

}

/*

*	函数名称:	AppendItem(LPCTSTR lpszFileName,LPCTSTR lpszComment)

*	说明:		在XML中添加一条日志

*	参数:	

*			IN	LPCTSTR lpszFileName	文件信息

*			IN  LPCTSTR lpszComment		错误信息

*/

void CXMLLogfile::AppendItem(LPCTSTR lpszFileName,LPCTSTR lpszComment)

{

	IXMLDOMElement *pRootNode, *element;

	IXMLDOMNode    *nLogItem;

	CComBSTR       szName;

	HRESULT hr;



	CTime timeCur ;

	timeCur = CTime::GetCurrentTime();

	CString strDate, strTime;

	strDate = timeCur.Format(_T("%Y-%m-%d"));

	strTime = timeCur.Format(_T("%X"));

	

	hr = m_pXMLDoc->get_documentElement(&pRootNode);



	m_pXMLDoc->createElement(CComBSTR(_T("LogItem")),&element);

	pRootNode->appendChild(element,&nLogItem);

	element->Release();



	AppendNode(nLogItem,_T("Date"),strDate);



	AppendNode(nLogItem,_T("Time"),strTime);



	AppendNode(nLogItem,_T("Filename"),lpszFileName);



	AppendNode(nLogItem,_T("comment"),lpszComment);





	pRootNode->Release();

}

/*

*	函数名称:	Flush()

*	说明:		将缓冲区内数据写到磁盘保存XML文件

*	参数:	

*				无

*/

void CXMLLogfile::Flush()

{

	m_pXMLDoc->save(COleVariant(m_strFileName));

}

/*

*	函数名称:	Log(LPCTSTR lpszFilName,LPCTSTR s,...)

*	说明:		添加一条日值记录

*	参数:	

*				LPCTSTR lpszFileName	文件信息

*				LPCTSTR	s				其他错误信息

*	EXAMPLE:

*			Log(__FILE__,"%ld line error!!",__LINE__)

*/

void CXMLLogfile::Log(LPCTSTR lpszFilName,LPCTSTR s,...)

{

	static TCHAR szBuff[1024];

	va_list argptr;

	int cnt;



	va_start(argptr, s);

	cnt = _vstprintf(szBuff, s, argptr);

	va_end(argptr);

	

	AppendItem(lpszFilName,szBuff);

	Flush();

}

/*

*	函数名称:	ClearAll()

*	说明:		清除日值

*	参数:	

*				无

*	返回值:		 成功 true

*/

bool CXMLLogfile::ClearAll()

{

	IXMLDOMElement *pRootNode= NULL;

	IXMLDOMNode    *pLogItem= NULL, *pLogData= NULL, *pOldNode= NULL, *pNextNode ,*pPreviousNode;

	CComBSTR       szName;

	HRESULT		hr ;

	m_pXMLDoc->get_documentElement(&pRootNode);

	try

	{

		pRootNode->get_lastChild(&pLogItem);

		do

		{

			pLogItem->get_previousSibling(&pPreviousNode);

				

			pLogItem->get_baseName(&szName);

			if(szName == CComBSTR(_T("LogItem"))) 

			{

				pLogItem->get_firstChild(&pLogData);

				do

				{

					pLogData->get_nextSibling(&pNextNode);



					pLogData->get_baseName(&szName);

					hr = pLogItem->removeChild(pLogData,&pOldNode);

					if (FAILED(hr))

						_com_issue_error(hr);

					pOldNode->Release();

					pOldNode = NULL;



					pLogData = pNextNode;

				}while(pLogData != NULL);



				hr = pRootNode->removeChild(pLogItem,&pOldNode);



				if (FAILED(hr))

				_com_issue_error(hr);

			}

			

			pLogItem = pPreviousNode;

		}while(pLogItem != NULL);

		pRootNode->Release();

	}

	catch(_com_error &e)

	{

		pRootNode->Release();

		DumpComError(e);

		return false;

	}

	Flush();

	return true;

}

(全文完) 下载本文示例代码


利用XML文件写日志的类利用XML文件写日志的类利用XML文件写日志的类利用XML文件写日志的类利用XML文件写日志的类利用XML文件写日志的类利用XML文件写日志的类利用XML文件写日志的类利用XML文件写日志的类利用XML文件写日志的类利用XML文件写日志的类利用XML文件写日志的类
阅读(251) | 评论(0) | 转发(0) |
0

上一篇:实现文件加密功能

下一篇:初识WTL(下)

给主人留下些什么吧!~~