Windows API ReportEvent 写系统日志

本文连接:https://www.cnblogs.com/jqdy/p/14993286.html

  Windows系统日志的API有两个版本。一个是适用于Windows Server 2003、Windows XP 或 Windows 2000,升级版适用于 Vista 及以后的版本。两个版本使用两套 API 函数。在高版本操作系统中,使用低版本函数写入的日志,仍然可以查看。

  低版本的一套函数比较简单明了,在一个简单的服务程序中进行了应用。其核心 API 就是写日志函数 ReportEvent() 。

  1. 函数及参数说明
 1 BOOL ReportEventA(
 2     HANDLE    hEventLog, 
 3     WORD      wType,
 4     WORD      wCategory,
 5     DWORD     dwEventID,
 6     PSID      lpUserSid,
 7     WORD      wNumStrings,
 8     DWORD     dwDataSize,
 9     LPCSTR *  lpStrings,
10     LPVOID    lpRawData
11 );     

  1.1     hEventLog:事件日志句柄,由 RegisterEventSource() 函数取得,使用完毕后用DeregisterEventSource() 函数释放。

  1.2     wType:日志消息类型,一共有六种,其作用就是在“日志查看器”的第一列“级别”中,显示不同的图标(共3种)。

类型枚举

含义

图标

EVENTLOG_SUCCESS

0x0000

消息事件

  

EVENTLOG_AUDIT_FAILURE

0x0010

审核失败事件

EVENTLOG_AUDIT_SUCCESS

0x0008

审核成功事件

 

EVENTLOG_ERROR_TYPE

0x0001

错误事件

 

EVENTLOG_INFORMATION_TYPE

0x0004

消息事件

 

EVENTLOG_WARNING_TYPE

0x0002

警告事件

 

  1.3     wCategory:特定来源的信息。通过 Message Files 按照自己的需要自定义 Event Category规则,以便于在日志查看器中进行相关提示。此值 = 0 时,日志查看器不能提示具体的文字信息,显示“无法找到来自源.....”。

  1.4     dwEventID:事件标识符。是一个32位的 DWORD,按位定义如下表所示。使用时通过位操作的方法将相关位进行组合。

  • Sev:严重性定义。00代表“成功”,01代表“信息”,10代表“警告”,11代表“错误”,对应着日志查看器“级别”列显示哪种图标。
  • C:系统和客户自定义代码标识位,0代表系统信息,1代表客户自定义。标识上表后16位表示的Code属于哪种信息。
  • R:保留位。
  • Facility:Message Files 中指定的设备号。默认0值代表着 Application。
  • Code:在日志查看器中对应“事件ID”列的号码。

  1.5     lpUserSid:指向当前用户的安全标识符的指针。如果不需要安全标识符,则此参数可以为NULL。

  1.6     wNumStrings:第8个参数 lpStrings 有几个字符串组成。

  1.7     dwDataSize:要写入日志的特定于事件的原始(二进制)数据的字节数。如果此参数为零,则不存在特定于事件的数据。对于只写入文本信息的情况,取0即可。

  1.8     lpStrings:类型为LPCSTR *,即CHAR**类型,代表一组字符串。这组字符串就是要写入日志的内容,有几个字符串由参数6:wNumStrings 指定。

  1.9     lpRawData:指向要写入的二进制数据的指针,其长度由参数7:dwDataSize指定,不需要写入二进制数据时取NULL。

 

 1 // 代码段......
 2 
 3 HANDLE hEventSource;
 4 DWORD dwEventIdentifer;
 5 
 6 // 前面给出了wErrorType,按照事件代码编码格式组织编码
 7 
 8     switch (wErrorType)
 9     {
10     case EVENTLOG_SUCCESS:
11         dwEventIdentifer = 0x00;
12         break;
13     case EVENTLOG_INFORMATION_TYPE:
14         dwEventIdentifer = 0x01;
15         break;
16     case EVENTLOG_WARNING_TYPE:
17         dwEventIdentifer = 0x02;
18         break;
19     case EVENTLOG_ERROR_TYPE:
20         dwEventIdentifer = 0x03;
21         break;
22     default:
23         break;
24     }
25     dwEventIdentifer <<= 30;                 // 移位获得Sev,前面给出的 wErrorType 为 EVENTLOG_ERROR_TYPE,对应着下图 “级别” 一列显示“错误”图标
26     dwEventIdentifer |= (WORD)wCustumerCode; // 前面自定义了Code,对应着下图中 事件ID 20
27 
28     hEventSource = RegisterEventSource(NULL, SVCNAME); // 宏 SVCNAME 定义了服务的名称 TEXT("SamplingService")
29 
30     if (NULL != hEventSource)
31     {
32 
33         LPCTSTR lpszStrings[2] = { SVCNAME, szMsg };//要写入日志的信息有两行,分别是 服务名,和前面给出的szMsg,对应着下图“以下是包含在事件中的信息”
34 
35         ReportEvent(
36             hEventSource,      // event log handle
37             wErrorType,        // event type
38             0,                 // event category
39             dwEventIdentifer,  // event identifier
40             NULL,              // no security identifier
41             2,                 // size of lpszStrings array
42             0,                 // no binary data
43             lpszStrings,       // array of strings
44             NULL);             // no binary data
45         DeregisterEventSource(hEventSource);
46     }
47 }

  在日志查看器中的效果:

   上图中显示“无法找到来自源.....”,是因为没有定义相关的Message File,不过可以通过提供单独帮助文件的形式进行详细说明。

posted @ 2021-07-10 11:10  jqdy  阅读(1227)  评论(0编辑  收藏  举报