将事件写入事件查看器
Posted
技术标签:
【中文标题】将事件写入事件查看器【英文标题】:Write an Event to the Event viewer 【发布时间】:2011-12-19 09:20:46 【问题描述】:我在 C# 中找到了一个如何将新事件添加到事件查看器的示例。 但是,我需要一个用 C++(不是 .NET)编写的示例,该示例在“应用程序”部分下为事件查看器创建新事件。
【问题讨论】:
这是一个更简单、直接的解决方案,可以让基本的事件日志记录正常工作:***.com/questions/37035958/… 【参考方案1】:您可以从 WINAPI 中使用这三个函数:
RegisterEventSource ReportEvent DeregisterEventSource这里是一个快速示例,说明如何使用它们并在事件日志中正确显示消息(为简洁起见,错误处理大多被忽略)。
从以下Event_log.mc
文件中创建一个包含消息信息的资源:
;#ifndef _EXAMPLE_EVENT_LOG_MESSAGE_FILE_H_
;#define _EXAMPLE_EVENT_LOG_MESSAGE_FILE_H_
MessageIdTypeDef=DWORD
SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS
Informational=0x1:STATUS_SEVERITY_INFORMATIONAL
Warning=0x2:STATUS_SEVERITY_WARNING
Error=0x3:STATUS_SEVERITY_ERROR
)
LanguageNames=(EnglishUS=0x401:MSG00401
Dutch=0x113:MSG00113
Neutral=0x0000:MSG00000
)
MessageId=0x0 SymbolicName=MSG_INFO_1
Severity=Informational
Facility=Application
Language=Neutral
%1
.
MessageId=0x1 SymbolicName=MSG_WARNING_1
Severity=Warning
Facility=Application
Language=Neutral
%1
.
MessageId=0x2 SymbolicName=MSG_ERROR_1
Severity=Error
Facility=Application
Language=Neutral
%1
.
MessageId=0x3 SymbolicName=MSG_SUCCESS_1
Severity=Success
Facility=Application
Language=Neutral
%1
.
;#endif
为了构建.mc
文件和.res
资源文件,我执行了以下操作:
mc.exe -A -b -c -h . -r resources Event_log.mc
rc.exe -foresources/Event_log.res resources/Event_log.rc
这将在当前目录中创建一个名为 Event_log.h
的头文件和一个 resources
目录,其中包含一个名为 Event_log.res
的文件,您必须将其链接到您的应用程序二进制文件。
例如main.cpp
:
#include <windows.h>
#include "Event_log.h"
void install_event_log_source(const std::string& a_name)
const std::string key_path("SYSTEM\\CurrentControlSet\\Services\\"
"EventLog\\Application\\" + a_name);
HKEY key;
DWORD last_error = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
key_path.c_str(),
0,
0,
REG_OPTION_NON_VOLATILE,
KEY_SET_VALUE,
0,
&key,
0);
if (ERROR_SUCCESS == last_error)
BYTE exe_path[] = "C:\\path\\to\\your\\application.exe";
DWORD last_error;
const DWORD types_supported = EVENTLOG_ERROR_TYPE |
EVENTLOG_WARNING_TYPE |
EVENTLOG_INFORMATION_TYPE;
last_error = RegSetValueEx(key,
"EventMessageFile",
0,
REG_SZ,
exe_path,
sizeof(exe_path));
if (ERROR_SUCCESS == last_error)
last_error = RegSetValueEx(key,
"TypesSupported",
0,
REG_DWORD,
(LPBYTE) &types_supported,
sizeof(types_supported));
if (ERROR_SUCCESS != last_error)
std::cerr << "Failed to install source values: "
<< last_error << "\n";
RegCloseKey(key);
else
std::cerr << "Failed to install source: " << last_error << "\n";
void log_event_log_message(const std::string& a_msg,
const WORD a_type,
const std::string& a_name)
DWORD event_id;
switch (a_type)
case EVENTLOG_ERROR_TYPE:
event_id = MSG_ERROR_1;
break;
case EVENTLOG_WARNING_TYPE:
event_id = MSG_WARNING_1;
break;
case EVENTLOG_INFORMATION_TYPE:
event_id = MSG_INFO_1;
break;
default:
std::cerr << "Unrecognised type: " << a_type << "\n";
event_id = MSG_INFO_1;
break;
HANDLE h_event_log = RegisterEventSource(0, a_name.c_str());
if (0 == h_event_log)
std::cerr << "Failed open source '" << a_name << "': " <<
GetLastError() << "\n";
else
LPCTSTR message = a_msg.c_str();
if (FALSE == ReportEvent(h_event_log,
a_type,
0,
event_id,
0,
1,
0,
&message,
0))
std::cerr << "Failed to write message: " <<
GetLastError() << "\n";
DeregisterEventSource(h_event_log);
void uninstall_event_log_source(const std::string& a_name)
const std::string key_path("SYSTEM\\CurrentControlSet\\Services\\"
"EventLog\\Application\\" + a_name);
DWORD last_error = RegDeleteKey(HKEY_LOCAL_MACHINE,
key_path.c_str());
if (ERROR_SUCCESS != last_error)
std::cerr << "Failed to uninstall source: " << last_error << "\n";
int main(int a_argc, char** a_argv)
const std::string event_log_source_name("my-test-event-log-source");
install_event_log_source(event_log_source_name);
log_event_log_message("hello, information",
EVENTLOG_INFORMATION_TYPE,
event_log_source_name);
log_event_log_message("hello, error",
EVENTLOG_ERROR_TYPE,
event_log_source_name);
log_event_log_message("hello, warning",
EVENTLOG_WARNING_TYPE,
event_log_source_name);
// Uninstall when your application is being uninstalled.
//uninstall_event_log_source(event_log_source_name);
return 0;
希望这会有所帮助,但请考虑@Cody Gray 所说的这种方法已被弃用。
【讨论】:
请注意,从 Windows Vista 开始,该 API 已被弃用。新应用程序应使用Windows Event Log API 记录事件。 @CodyGray,ta。从来不知道。旧的 API 仍然有效(据我所知),但我在 Vista 和 Windows 7 上使用它没有问题。 嗨,正如我之前提到的,描述给出了一般描述,我可以在最后添加一些内容,但不会更改“事件查看器”中的整个描述。如果您能指出一个可以在使用 ReportEvent 函数时更改描述的示例,我将不胜感激 首先我要感谢您的完整描述。我正在尝试使用 mc.exe 对其进行编译,但出现错误。您使用哪个 mc.exe? (错误:MC:无效开关:A MC:无效开关:b Microsoft (R) Message Compiler Version 1.00.5239) mc.ex 从 C:\Program Files\Microsoft Visual Studio\VC98\Bin\mc.exe 运行) 尝试添加到.obj
文件列表。此外,您将需要重新启动事件查看器。【参考方案2】:
您正在寻找有关Windows Event Log API 的文档。您需要调用本机 Win32 API 函数,而不是使用 .NET Framework 的包装器,因为您使用的是非托管 C++。
如果您的目标是 Windows Vista 之前的操作系统(XP、Server 2003 等),则需要改用较旧的 Event Logging API。
【讨论】:
您好,我使用了您附加到 Microsoft 的链接,并且有一个很好的示例。但是,没有更改描述的选项,当我转到“事件查看器”并打开描述时,我发现以下行:“找不到源 (MyEventProvider) 中事件 ID (259) 的描述。本地计算机可能没有必要的注册表信息或消息 DLL 文件来显示来自远程计算机的消息。您可以使用 /AUXSOURCE= 标志来检索此描述;有关详细信息,请参阅帮助和支持。以下信息是事件:" 两个链接都指向同一个 URL。以上是关于将事件写入事件查看器的主要内容,如果未能解决你的问题,请参考以下文章