我正在使用旧的Event Logging API使用C ++将事件写入事件日志。
我可以写入应用程序日志,但是我无法写入系统日志(我根据我在网上找到的一些教程编写了代码)。
这是我的MessageDef.mc
文件:
MessageIdTypeDef=DWORD
SeverityNames=(
Success=0x0:STATUS_SUCCESS
Informational=0x1:STATUS_INFORMATIONAL
Warning=0x2:STATUS_WARNING
Error=0x3:STATUS_ERROR
)
FacilityNames=(
System=0x0FF:FACILITY_SYSTEM
Application=0xFFF:FACILITY_APPLICATION
)
LanguageNames=(
EnglishUS=0x401:LAN_ENGLISHUS
Neutral=0x0:LAN_NEUTRAL
)
MessageId=0x0 SymbolicName=MSG_APPLOG
Severity=Informational
Facility=Application
Language=EnglishUS
%1
.
MessageId=0x1 SymbolicName=MSG_SYSLOG
Severity=Informational
Facility=System
Language=EnglishUS
%1
.
这是包含安装,注册事件源并生成事件的代码的文件:
#include "CommonTasks.h"
#include "EventGen.h"
int InstallEventLogSource(char *strExeName, char *strLogName)
{
std::string sLogName(strLogName), sExeName(strExeName);
std::string sLogKeyPathString = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\" + sLogName + "\\" + sExeName;
HKEY hKey;
DWORD status = RegCreateKeyEx(HKEY_LOCAL_MACHINE, sLogKeyPathString.c_str(), 0, 0, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, 0, &hKey, 0);
if(status == ERROR_SUCCESS)
{
char strFullExeName[MAX_EXE_NAME];
GetModuleFileName(NULL, strFullExeName, MAX_EXE_NAME);
BYTE bptrFullExeName[strlen(strFullExeName) + 1];
strcpy((char *)bptrFullExeName, strFullExeName);
status = RegSetValueEx(hKey, "EventMessageFile", 0, REG_SZ, bptrFullExeName, sizeof(bptrFullExeName));
if(status == ERROR_SUCCESS)
{
DWORD dwSeveritySupported = EVENTLOG_INFORMATION_TYPE;
status = RegSetValueEx(hKey, "TypesSupported", 0, REG_DWORD, (LPBYTE)&dwSeveritySupported, sizeof(dwSeveritySupported));
}
}
RegCloseKey(hKey);
}
int UninstallEventLogSource(char *strAppName, char *strLogName)
{
std::string sLogName(strLogName), sAppName(strAppName);
std::string sLogKeyPathString = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\" + sLogName + "\\" + sAppName;
DWORD status = RegDeleteKey(HKEY_LOCAL_MACHINE, sLogKeyPathString.c_str());
}
int WriteEventToLog(char *strMessage, char *strLogName, char *strLogSourceName)
{
DWORD dwEventId;
std::string sLogName(strLogName);
if(sLogName == "Application")
dwEventId = MSG_APPLOG;
else if(sLogName == "System")
dwEventId = MSG_SYSLOG;
HANDLE hEventLog = RegisterEventSource(0, strLogSourceName);
if(hEventLog)
{
ReportEvent(hEventLog, EVENTLOG_INFORMATION_TYPE, 0, dwEventId, 0, 1, 0,(const char **)&strMessage, 0);
}
DeregisterEventSource(hEventLog);
}
void GenerateEvents(int iEvtCount, char *strLogName)
{
char *strExeName = NULL;
GetExeName(&strExeName);
InstallEventLogSource(strExeName, strLogName);
WriteEventToLog("1", strLogName, strExeName);
UninstallEventLogSource(strExeName, strLogName);
}
我正在使用我的应用程序的exe名称在所需的日志下创建一个键(从另一个文件中的另一个调用方法传入),该键可以是Application或System。我是源和生成事件的注册表。
但是,即使我指定了System,我也可以看到正在创建的密钥,但所有这些事件只会转到应用程序日志。
我做错了什么?
此外,我假设mc文件中的FacilityNames
部分引用要写入的日志(没有关于此的良好文档)。这是对的吗?
答案 0 :(得分:0)
如果您尝试将消息记录到无法找到的事件源,则事件将转到应用程序日志。仅仅创建一个事件源的子键可能还不够。在Vista之前,您需要在parent log's key中添加/更新类型为Sources
的{{1}}值,以指定可写入该日志的事件源。除非您仅定位Vista及更高版本,否则您不会采取这一步骤。
Windows应该监视日志的子键并为您维护REG_MULTI_SZ
,但根据我的经验并不总是正常工作。在Vista之前,如果您没有自己使Sources
保持最新状态,则事件日志服务不会及时检测到动态添加/删除的事件源(如果有的话)。
不,Sources
与您可以写入的日志无关。它仅定义了在指定消息ID的FacilityNames
位时可以使用的符号名称,而不是指定硬编码的数字。没什么。
唯一指示您撰写任何给定消息的日志是您在facility
中指定的事件源。在注册写入源之前,必须确保源作为目标日志密钥的子项存在,并且还存在于Vista之前的日志RegisterEventSource()
值中。