博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Windows c++应用程序通用日志组件(组件及测试程序下载)
阅读量:6621 次
发布时间:2019-06-25

本文共 19571 字,大约阅读时间需要 65 分钟。

引言

  众所周知,在调试、跟踪和执行应用程序的过程中,程序的日志能为这些工作提供大量有价值的运行信息。因此,程序的日志对应用程序的运行、维护至关重要。

  在如何记录程序日志方面,通常有三种选择:

  1、采用Log4CXX等公共开源日志组件:这类日志组件的特点是跨平台且功能比较强大,例如可以把日志发往另一台服务器或记录到数据库中等; 另外,可配置性较高,可以通过配置文件或程序代码对日志进行很多个性化设置。但从另外一个角度看,由于这些优点往往也导致了在使用方面的缺点。首先,对于 一般应用程序来说,它们并不需要太多的功能,通常只需要把日志记录到文件或反馈到应用程序,功能太多反正让用户使用起来觉得繁琐还得背负很多从来都用不到 的代码。其次,这类日志组件通常是跨平台的,并不只是针对 Windows 或 VC 的应用程序,因此使用起来总会觉得有点别扭,例如他们的字符都是用 char 类型的,对于一个 Unicode 程序来说每次写日志都要做字符转换是很不爽的事情,本座在多年前曾经使用过 Log4Cpp ,程序执行时总是报告日志组件有内存泄露,虽然有可能是误报,但是使用起来总觉得很不舒服。

  2、自己写几个简单的类或函数记录日志:这种方法的确很简单,通常都不用一两百行的代码。但这种方法通常缺乏规范性和通用性,其他程序需要记录 类似的但有点差异的日志时,通常的作法是:Copy-Paste-Modify;另外,这类方法很可能也没有考虑性能或并发方面的问题,通常是直接在工作 线程中写日志,对于那些性能要求较高的应用程序是绝对不允许的。

  3、干脆不记录任何日志:的确,现在很多程序由于各种原因并没有记录任何日志。但本座以为,如果一个程序是有用的,具备一定功能,并且需要连续运行较长一段时间,那么记录日志是必须的;否则,得认真考虑该程序是否有存在的必要了。

 


设计

  综上所述,编写一个通用的日志组件应该着重考虑三个方面:功能、可用性和性能。下面,本座详细说明在设计日志组件时对这些方面问题的考虑:

  1、功能:本日志组件的目的是满足大多数应用程序记录日志的需求 —— 把日志输出到文件或发送到应用程序中,并不提供一些复杂但不常用的功能。本日志组件的功能包括:

  • 把日志信息输出到指定文件
  • 每日生成一个日志文件
  • 对于 GUI 程序,可以把日志信息发送到指定窗口
  • 对于Console应用程序,可以把日志信息发往标准输出 (std::cout)
  • 支持 MBCS / UNICODE,Console / GUI 程序
  • 支持动态加载和静态加载日志组件 DLL
  • 支持 DEBUG/TRACE/INFO/WARN/ERROR/FATAL 等多个日志级别

  2、可用性:本日志组件着重考虑了可用性,尽量让使用者用起来觉得简便、舒心:

  • 简单纯净:不依赖任何程序库或框架
  • 使用接口简单,不需复杂的配置或设置工作
  • 提供 CStaticLogger 和 CDynamicLogger 包装类用于静态或动态加载以及操作日志组件,用户无需关注加载细节
  • 程序如果要记录多个日志文件只需为每个日志文件创建相应的 CStaticLogger 或 CDynamicLogger 对象
  • 只需调用 Log()/Debug()/Trace()/Info()/Warn()/Error()/Fatal() 等方法记录日志
  • 日志记录方法支持可变参数
  • 日志输出格式:<时间> <线程ID> <日志级别> <日志内容>

  3、性能:性能是组件是否值得使用的硬指标,本组件从设计到编码的过程都尽量考虑到性能优化:

  • 支持多线程同时发送写日志请求
  • 使用单独线程在后台写日志,不影响工作线程的正常执行
  • 采用批处理方式批量记录日志

 


接口

  1、ILogger:日志组件对象接口

1 /******************************************************************************  2 Module:  Logger.h  3 Notices: Copyright (c) 2012 Bruce Liang - http://www.cnblogs.com/ldcsaa/  4   5 Purpose: 记录程序日志。  6         1. 把日志信息输出到指定文件  7         2. 对于 GUI 程序,可以把日志信息发送到指定窗口  8         3. 对于Console应用程序,可以把日志信息发往标准输出 (std::cout)  9  10 Desc: 11         1、功能: 12         -------------------------------------------------------------------------------------- 13         a) 把日志信息输出到指定文件 14         b) 每日生成一个日志文件 15         c) 对于 GUI 程序,可以把日志信息发送到指定窗口 16         d) 对于Console应用程序,可以把日志信息发往标准输出 (std::cout) 17         e) 支持 MBCS / UNICODE,Console / GUI 程序 18         f) 支持动态加载和静态加载日志组件 DLL 19         g) 支持 DEBUG/TRACE/INFO/WARN/ERROR/FATAL 等多个日志级别 20          21         2、可用性: 22         -------------------------------------------------------------------------------------- 23         a) 简单纯净:不依赖任何程序库或框架 24         b) 使用接口简单,不需复杂的配置或设置工作 25         c) 提供 CStaticLogger 和 CDynamicLogger 包装类用于静态或动态加载以及操作日志组件,用户无需关注加载细节 26         d) 程序如果要记录多个日志文件只需为每个日志文件创建相应的 CStaticLogger 或 CDynamicLogger 对象 27         e) 只需调用 Log()/Debug()/Trace()/Info()/Warn()/Error()/Fatal() 等方法记录日志 28         f) 日志记录方法支持可变参数 29         g) 日志输出格式:
<时间>
<线程id>
<日志级别>
<日志内容>
30 31 3、性能: 32 -------------------------------------------------------------------------------------- 33 a) 支持多线程同时发送写日志请求 34 b) 使用单独线程在后台写日志,不影响工作线程的正常执行 35 c) 采用批处理方式批量记录日志 36 37 Usage: 38 方法一:(静态加载 Logger DLL) 39 -------------------------------------------------------------------------------------- 40 0. 应用程序包含 StaticLogger.h 头文件 41 1. 创建 CStaticLogger 对象(通常为全局对象) 42 2. 调用 CStaticLogger->Init(...) 初始化日志组件 43 3. 使用 CStaticLogger->Log()/Debug()/Trace()/Info()/Warn()/Error()/Fatal() 等方法写日志 44 4. 调用 CStaticLogger->UnInit(...) 清理日志组件(CStaticLogger 对象析构时也会自动清理日志组件) 45 46 方法二:(动态加载 Logger DLL) 47 -------------------------------------------------------------------------------------- 48 0. 应用程序包含 DynamicLogger.h 头文件 49 1. 创建 CDynamicLogger 对象(通常为全局对象) 50 2. 调用 CDynamicLogger->Init(...) 初始化日志组件 51 3. 使用 CDynamicLogger->Log()/Debug()/Trace()/Info()/Warn()/Error()/Fatal() 等方法写日志 52 4. 调用 CDynamicLogger->UnInit(...) 清理日志组件(CDynamicLogger 对象析构时也会自动清理日志组件) 53 54 方法三:(直接用导出函数加载 Logger DLL) 55 -------------------------------------------------------------------------------------- 56 0. 应用程序包含 Logger.h 头文件 57 1. 手工调用 ILoger_Create() 和 ILoger_Create() 导出函数创建和销毁 ILogger 对象 58 (注:如果是动态加载,需手工调用 ::LoadLibrary()/::FreeLibrary() 系列 API 函数加载和卸载 Logger DLL) 59 60 [ 61 ***** 对于希望通过窗口接收日志信息的 GUI 程序 ***** 62 63 A. 日志组件初始化成功后调用 SetGUIWindow(HWND) 设置收日志的窗口 64 B. 窗口须响应处理 LOG_MESSAGE 消息 65 C. 处理完 LOG_MESSAGE 消息后,调用 ILogger::FreeLogMsg() 销毁接收到的 TLogMsg 66 ] 67 68 Environment: 69 1. Windows 2000 or later (_WIN32_WINNT >= 0x0500) 70 2. VC++ 2010 or later 71 72 Release: 73 1. Logger_C.dll - Console/MBCS/Release 74 2. Logger_CD.dll - Console/MBCS/Debug 75 3. Logger_CU.dll - Console/Unicode/Release 76 4. Logger_CUD.dll - Console/Unicode/Debug 77 5. Logger.dll - GUI/MBCS/Release 78 6. Logger_D.dll - GUI/MBCS/Debug 79 7. Logger_U.dll - GUI/Unicode/Release 80 8. Logger_UD.dll - GUI/Unicode/Debug 81 82 Examples: 83 1. TestGUILogger - GUI 版测试程序 (静态加载) 84 2. TestDynamicLogger - GUI 版测试程序 (动态加载) 85 3. TestConsoleLogger - Console 版测试程序 (静态加载) 86 87 ******************************************************************************/ 88 89 #pragma once 90 91 /**************************************************/ 92 /********** imports / exports Logger.dll **********/ 93 94 #ifdef LOGGER_EXPORTS 95 #define LOGGER_API __declspec(dllexport) 96 //#define TRY_INLINE inline 97 #else 98 #define LOGGER_API __declspec(dllimport) 99 //#define TRY_INLINE100 #endif101 102 /**************************************************/103 /****************** 日志组件接口 *******************/104 105 class LOGGER_API ILogger106 {107 public:108 /***** 日志级别 *****/109 enum LogLevel110 {111 LL_NONE = 0XFF,112 LL_DEBUG = 1,113 LL_TRACE = 2,114 LL_INFO = 3,115 LL_WARN = 4,116 LL_ERROR = 5,117 LL_FATAL = 6118 };119 120 /***** 操作错误码 *****/121 enum ErrorCode122 {123 // 无错误124 EC_OK = NO_ERROR,125 // 文件操作相关的错误126 EC_FILE_GENERIC,127 EC_FILE_FILENOTFOUND,128 EC_FILE_BADPATH,129 EC_FILE_TOMANYOPERFILES,130 EC_FILE_ACCESSDENIED,131 EC_FILE_INVALIDFILE,132 EC_FILE_REMOVECURRENTDIR,133 EC_FILE_DIRECTORYFULL,134 EC_FILE_BADSEEK,135 EC_FILE_HARDIO,136 EC_FILE_SHARINGVIOLATION,137 EC_FILE_LOCKVIOLATION,138 EC_FILE_DISKFULL,139 EC_FILE_ENDOFFILE,140 // 其他错误141 EC_INVALID_STATE,142 EC_INIT_LOGLEVEL,143 EC_INIT_PRINTFLAG,144 EC_INIT_CREATE_LOG_THREAD_FAIL145 };146 147 /******************************************148 日志信息结构149 *******************************************/150 struct TLogMsg151 {152 DWORD m_dwSize; // 结构大小 - 跟据消息长度动态变化153 LogLevel m_logLevel; // 日志级别154 UINT m_uiThreadID; // 线程ID155 SYSTEMTIME m_stMsgTime; // 记录时间156 TCHAR m_psMsg[1]; // 消息内容157 };158 159 public:160 ILogger(void);161 virtual ~ILogger(void);162 private:163 ILogger(const ILogger&);164 ILogger& operator = (const ILogger&);165 166 public:167 // 日志组件初始化方法168 virtual BOOL Init(169 LPCTSTR logFile = NULL // 日志文件. 默认: {AppPath}/logs/{AppName}-YYYYMMDD.log170 , LogLevel ll = DEFAULT_LOG_LEVEL // 日志级别. 默认: [Debug -> LL_DEBUG] / [Release -> LL_INFO]171 , int printFlag = DEFAULT_PRINT_FLAG // 输出掩码. 是否输出到文件和(或)屏幕. 默认: 只输出到文件172 ) = 0;173 // 日志组件清理方法174 virtual BOOL UnInit() = 0;175 176 public:177 // 写日志方法:传入日志内容字符串(对于不需要格式化的日志文本,用本方法效率最高)178 virtual void Log_0 (LogLevel ll, LPCTSTR msg) = 0;179 virtual void Debug_0(LPCTSTR msg);180 virtual void Trace_0(LPCTSTR msg);181 virtual void Info_0 (LPCTSTR msg);182 virtual void Warn_0 (LPCTSTR msg);183 virtual void Error_0(LPCTSTR msg);184 virtual void Fatal_0(LPCTSTR msg);185 186 // 写日志方法:传入格式化字符串和参数栈指针(通常只在组件内部使用)187 virtual void LogV (LogLevel ll, LPCTSTR format, va_list arg_ptr);188 189 // 写日志方法:传入格式化字符串和可变参数(非常灵活简便)190 virtual void Log (LogLevel ll, LPCTSTR format, ...);191 virtual void Debug (LPCTSTR format, ...);192 virtual void Trace (LPCTSTR format, ...);193 virtual void Info (LPCTSTR format, ...);194 virtual void Warn (LPCTSTR format, ...);195 virtual void Error (LPCTSTR format, ...);196 virtual void Fatal (LPCTSTR format, ...);197 198 // 写日志方法:传入格式化字符串和可变参数(与上一组方法类似,但在进行任何操作前会检查日志级别)199 virtual void TryLog (LogLevel ll, LPCTSTR format, ...);200 virtual void TryDebug (LPCTSTR format, ...);201 virtual void TryTrace (LPCTSTR format, ...);202 virtual void TryInfo (LPCTSTR format, ...);203 virtual void TryWarn (LPCTSTR format, ...);204 virtual void TryError (LPCTSTR format, ...);205 virtual void TryFatal (LPCTSTR format, ...);206 207 // 通用辅助方法208 virtual BOOL HasInited () const = 0; // 是否已经初始化 209 virtual BOOL IsPrint2File () const = 0; // 是否把日志输出到文件 210 virtual BOOL IsPrint2Screen () const = 0; // 是否把日志输出到屏幕窗口 211 virtual int GetPrintFlag () const = 0; // 打印标志 212 virtual LogLevel GetLogLevel () const = 0; // 日志级别 213 virtual LPCTSTR GetLogFile() const = 0; // 日志文件214 virtual ErrorCode GetLastError() const = 0; // 当前操作错误码215 216 /****************************** GUI ******************************/217 #ifdef _WINDOWS218 public:219 // 设置接收日志信息的窗口, hWndGUI == NULL 则取消接收220 virtual void SetGUIWindow(HWND hWndGUI) = 0;221 // 获取接收日志信息的窗口222 virtual HWND GetGUIWindow() = 0;223 224 // 销毁在发送 LOG_MESSAGE 消息时动态创建的 TLogMsg 对象225 virtual void FreeLogMsg(const TLogMsg* pLogMsg);226 227 // 虚拟窗口句柄标掩码:用于向 GUI 窗口发送 LOG_MESSAGE 消息时作为发送源标识228 static const int LOGGER_FAKE_WINDOW_BASE = 0X80001111;229 // 自定义日志消息:通过本消息向 GUI 窗口发送日志230 // 其中:WPARAM -> ILogger 对象指针,LPARAM -> TLogMsg 结构体指针231 static const int LOG_MESSAGE = WM_USER | (0x7FFF & LOGGER_FAKE_WINDOW_BASE);232 #endif233 234 public:235 static const int PRINT_FLAG_FILE = 0x00000001; // 打印到文件236 static const int PRINT_FLAG_SCREEN = 0x00000002; // 打印到屏幕237 static const int DEFAULT_PRINT_FLAG = PRINT_FLAG_FILE; // 默认日志掩码238 static const LogLevel DEFAULT_LOG_LEVEL = 239 #ifdef _DEBUG240 LL_DEBUG241 #else242 LL_INFO243 #endif244 ;245 };246 247 /**************************************************/248 /************** Logger DLL 导出函数 ***************/249 250 // 创建 ILogger 对象251 EXTERN_C LOGGER_API ILogger* ILogger_Create();252 // 销毁 ILogger 对象253 EXTERN_C LOGGER_API void ILogger_Destroy(ILogger* p);254 255 // 获取各日志级别的文字描述256 EXTERN_C LOGGER_API LPCTSTR ILogger_GetLogLevelDesc (ILogger::LogLevel ll);257 // 获取各操作错误码的文字描述258 EXTERN_C LOGGER_API LPCTSTR ILogger_GetErrorDesc (ILogger::ErrorCode ec);

 

   代码中的注释基本已经能够说明日志组件的使用方法,这里只做一些简单的概括:

  版本:日志组件以 DLL 的形式提供,已编译成 Debug/Release、MBCS/Unicode、GUI/Console 8个版本

  测试:三个测试程序 TestGUILogger、TestDynamicLogger 和 TestConsoleLogger 用于测试所有版本。其中 TestDynamicLogger 采用动态加载方式加载 Logger DLL

  使用方法:

    0. 应用程序包含 Logger.h 头文件

    1. 调用 ILogger_Create() 导出函数创建 ILogger 对象
    2. 调用 ILogger->Init(...) 初始化日志组件
    3. 使用 ILogger->Log()/Debug()/Trace()/Info()/Warn()/Error()/Fatal() 等方法写日志
    4. 调用 ILogger->UnInit(...) 清理日志组件
    5. 调用 ILogger_Destroy() 导出函数销毁 ILogger 对象
 

  2、CStaticLogger:ILogger 包装器(智能指针)—— 用于静态加载 Logger DLL 

1 #pragma once 2  3 #include "Logger.h" 4  5 /**************************************************/ 6 /********* http://www.cnblogs.com/ldcsaa/ *********/ 7 /********** ILogger 包装器(智能指针) ***********/ 8 /*********** 用于静态加载 Logger DLL ************/ 9 10 class LOGGER_API CStaticLogger11 {12 public:13     // 构造函数:如果 bCreate 为 TRUE,则在构建 CStaticLogger 实例的同时创建 ILogger 对象14     CStaticLogger(BOOL bCreate = TRUE);15     // 析构函数16     ~CStaticLogger();17 private:18     CStaticLogger(const CStaticLogger&);19     CStaticLogger& operator = (const CStaticLogger&);20 21 public:22     inline void Reset           (ILogger* pLogger);     // 重设其封装的 ILogger 指针23     inline BOOL IsValid         ()    const;            // 判断其封装的 ILogger 指针是否非空24     inline ILogger* Get         ()    const;            // 获取 ILogger 指针25     inline ILogger& operator *  ()    const;            // 获取 ILogger 引用26     inline ILogger* operator -> ()    const;            // 获取 ILogger 指针27     inline operator ILogger*    ()    const;            // 转换为 ILogger 指针28 29 private:30     ILogger* m_pLogger;31 };

 

  CStaticLogger 为简化日志组件使用而设计,用于静态加载 Logger DLL 的场合。使用方法:

    0. 应用程序包含 StaticLogger.h 头文件

    1. 创建 CStaticLogger 对象(通常为全局对象)
    2. 调用 CStaticLogger->Init(...) 初始化日志组件
    3. 使用 CStaticLogger->Log()/Debug()/Trace()/Info()/Warn()/Error()/Fatal() 等方法写日志
    4. 调用 CStaticLogger->UnInit(...) 清理日志组件(CStaticLogger 对象析构时也会自动清理日志组件)

 

  3、CDynamicLogger:ILogger 包装器(智能指针)—— 用于动态加载 Logger DLL 

1 #pragma once  2   3 #include "Logger.h"  4   5 /**************************************************/  6 /********* http://www.cnblogs.com/ldcsaa/ *********/  7 /************** Logger DLL 默认文件名 ***************/  8   9 #ifdef _DEBUG 10     #ifdef _UNICODE 11         #ifdef _WINDOWS 12             #define DEF_LOGGER_DLL_FILE_PATH    _T("Logger_UD.dll") 13         #else 14             #define DEF_LOGGER_DLL_FILE_PATH    _T("Logger_CUD.dll") 15         #endif 16     #else 17         #ifdef _WINDOWS 18             #define DEF_LOGGER_DLL_FILE_PATH    _T("Logger_D.dll") 19         #else 20             #define DEF_LOGGER_DLL_FILE_PATH    _T("Logger_CD.dll") 21         #endif 22     #endif 23 #else 24     #ifdef _UNICODE 25         #ifdef _WINDOWS 26         #define DEF_LOGGER_DLL_FILE_PATH        _T("Logger_U.dll") 27         #else 28             #define DEF_LOGGER_DLL_FILE_PATH    _T("Logger_CU.dll") 29         #endif 30     #else 31         #ifdef _WINDOWS 32             #define DEF_LOGGER_DLL_FILE_PATH    _T("Logger.dll") 33         #else 34             #define DEF_LOGGER_DLL_FILE_PATH    _T("Logger_C.dll") 35         #endif 36     #endif 37 #endif 38  39 /**************************************************/ 40 /*************** Logger DLL 导出函数 ***************/ 41  42 // 创建 ILogger 对象 43 typedef ILogger*            (*FN_ILogger_Create)            (); 44 // 销毁 ILogger 对象 45 typedef void                (*FN_ILogger_Destroy)           (ILogger* p); 46 // 获取各日志级别的文字描述 47 typedef LPCTSTR             (*FN_ILogger_GetLogLevelDesc)   (ILogger::LogLevel ll); 48 // 获取各操作错误码的文字描述 49 typedef LPCTSTR             (*FN_ILogger_GetErrorDesc)      (ILogger::ErrorCode ec); 50  51 /*************************************************/ 52 /********** ILogger 包装器(智能指针) ***********/ 53 /************ 用于动态加载 Logger DLL ************/ 54  55 class CDynamicLogger 56 { 57 public: 58     // 构造函数:如果 bLoad 为 TRUE,则在构建 CDynamicLogger 示例的同时创建 ILogger 对象 59     CDynamicLogger(BOOL bLoad = TRUE, LPCTSTR lpszFilePath = DEF_LOGGER_DLL_FILE_PATH) 60     { 61         Reset(); 62  63         if(bLoad) 64             Load(lpszFilePath); 65     } 66  67     // 析构函数 68     ~CDynamicLogger() 69     { 70         Free(); 71     } 72  73 private: 74     CDynamicLogger(const CDynamicLogger&); 75     CDynamicLogger& operator = (const CDynamicLogger&); 76  77 public: 78     // 创建 ILogger 对象 79     ILogger* ILogger_Create() 80         {
return m_fnILoggerCreate();} 81 // 销毁 ILogger 对象 82 void ILogger_Destroy(ILogger* p) 83 {m_fnILoggerDestroy(p);} 84 // 获取各日志级别的文字描述 85 LPCTSTR ILogger_GetLogLevelDesc(ILogger::LogLevel ll) 86 {
return m_fnILoggerGetLogLevelDesc(ll);} 87 // 获取各操作错误码的文字描述 88 LPCTSTR ILogger_GetErrorDesc(ILogger::ErrorCode ec) 89 {
return m_fnILoggerGetErrorDesc(ec);} 90 91 // 加载 Logger DLL 92 BOOL Load(LPCTSTR lpszFilePath = DEF_LOGGER_DLL_FILE_PATH) 93 { 94 if(IsValid()) 95 return FALSE; 96 97 BOOL isOK = FALSE; 98 m_hLogger = ::LoadLibrary(lpszFilePath); 99 100 if(m_hLogger)101 {102 m_fnILoggerCreate = (FN_ILogger_Create) ::GetProcAddress(m_hLogger, "ILogger_Create");103 m_fnILoggerDestroy = (FN_ILogger_Destroy) ::GetProcAddress(m_hLogger, "ILogger_Destroy");104 m_fnILoggerGetLogLevelDesc = (FN_ILogger_GetLogLevelDesc) ::GetProcAddress(m_hLogger, "ILogger_GetLogLevelDesc");105 m_fnILoggerGetErrorDesc = (FN_ILogger_GetErrorDesc) ::GetProcAddress(m_hLogger, "ILogger_GetErrorDesc");106 107 if(m_fnILoggerCreate && m_fnILoggerDestroy)108 {109 m_pLogger = ILogger_Create();110 isOK = (m_pLogger != NULL);111 }112 }113 114 if(!isOK)115 Free();116 117 return isOK;118 }119 120 // 卸载 Logger DLL121 BOOL Free()122 {123 if(!IsValid())124 return TRUE;125 126 BOOL isOK = TRUE;127 128 if(m_pLogger) ILogger_Destroy(m_pLogger);129 if(m_hLogger) isOK = ::FreeLibrary(m_hLogger);130 131 Reset();132 133 return isOK;134 }135 136 BOOL IsValid () const {
return m_pLogger != NULL;} // 判断其封装的 ILogger 指针是否非空137 ILogger* Get () const {
return m_pLogger;} // 获取 ILogger 指针138 ILogger& operator * () const {
return *m_pLogger;} // 获取 ILogger 引用139 ILogger* operator -> () const {
return m_pLogger;} // 获取 ILogger 指针140 operator ILogger* () const {
return m_pLogger;} // 转换为 ILogger 指针141 142 private:143 void Reset()144 {145 m_hLogger = NULL;146 m_pLogger = NULL;147 m_fnILoggerCreate = NULL;148 m_fnILoggerDestroy = NULL;149 m_fnILoggerGetLogLevelDesc = NULL;150 m_fnILoggerGetErrorDesc = NULL;151 }152 153 private:154 HMODULE m_hLogger;155 ILogger* m_pLogger;156 157 FN_ILogger_Create m_fnILoggerCreate;158 FN_ILogger_Destroy m_fnILoggerDestroy;159 FN_ILogger_GetLogLevelDesc m_fnILoggerGetLogLevelDesc;160 FN_ILogger_GetErrorDesc m_fnILoggerGetErrorDesc;161 };

 

  CDynamicLogger 为简化日志组件使用而设计,用于动态加载 Logger DLL 的场合。使用方法:

    0. 应用程序包含 DynamicLogger.h 头文件

    1. 创建 CDynamicLogger 对象(通常为全局对象)
    2. 调用 CDynamicLogger->Init(...) 初始化日志组件
    3. 使用 CDynamicLogger->Log()/Debug()/Trace()/Info()/Warn()/Error()/Fatal() 等方法写日志
    4. 调用 CDynamicLogger->UnInit(...) 清理日志组件(CDynamicLogger 对象析构时也会自动清理日志组件) 

 

   ()

 

转自:

本文转自夏雪冬日博客园博客,原文链接:http://www.cnblogs.com/heyonggang/archive/2012/12/25/2831803.html,如需转载请自行联系原作者

你可能感兴趣的文章
format的用法
查看>>
DHCPv6 server port and DHCPv6 client port
查看>>
10个最佳的触控手式的JavaScript框架(转)
查看>>
BitmapFactory.Options避免 内存溢出 OutOfMemoryError的优化方法
查看>>
Python中通过Image的open之后,去show结果打不开bmp图片,无法正常显示图片
查看>>
DNGuard 免费的DotNet加密保护工具 V1.0
查看>>
编程中的命名设计
查看>>
easyui form validate总是返回false原因
查看>>
在(CListView)列表视图中添加右键菜单的方法
查看>>
打SharePoint 2010 SP1后访问用户配置文件同步服务应用程序出错的解决办法
查看>>
推荐《HeadFirst设计模式》
查看>>
Android中的onActivityResult和setResult方法的使用
查看>>
word双栏排版,最后一页由于分节符造成最后一页是空白页,删除分节符双栏就变成了单栏...
查看>>
手机web不同屏幕字体大小高度自适应
查看>>
服务器端口及连接及应用程序间的关系
查看>>
Android监听HOME键的最简单的方法
查看>>
Java 数组
查看>>
inotify+rsync实现实时同步
查看>>
C#GUID
查看>>
ASP.NET 5 入门(1) - 建立和开发ASP.NET 5 项目
查看>>