利用XML文件的一个写日志的类!!!!!

    技术2022-05-11  85

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

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

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

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

    以下是源代码,需要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

    //Author : By force eagle//Date time : 2003-5-26 17:08//reference : //    CXMLProfile By Emilio Guijarro Cameros

    #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_FILEstatic char THIS_FILE[]=__FILE__;#define new DEBUG_NEW#endif

    //// Construction/Destruction///*static TCHAR *szLogOrig= {_T(" /n" " /n" "/nXXXX/n1053925276.381/n" "2003-05-26/n13:01:16.861/n/n")};//*/static WCHAR *wszLogOrig = {L" /n /n/nXXXX/n1053925276.381/n2003-05-26/n13:01:16.861/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;}


    最新回复(0)