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 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,不过可以通过提供单独帮助文件的形式进行详细说明。