我试图在 C++ 应用程序中使用 EventLog 进行作弊。我没有消息文件;我只是按顺序使用
RegisterEventSource()
和 ReportEvent()
。
#include <windows.h>
#include <stdio.h>
int main()
{
LPCWSTR pInsertStrings[1] = { NULL };
HANDLE hEventLog = RegisterEventSource(NULL, L"AaaAaa");
if (NULL == hEventLog) exit(0);
Sleep(200);
// This event uses insert strings.
pInsertStrings[0] = L"Test event from AaaAaa";
ReportEvent(hEventLog, EVENTLOG_INFORMATION_TYPE, /*cat*/ 100,
/*evId*/ 0, /*uId*/ NULL, /*msgs*/ 1,
/*msgSz*/ 0, (LPCWSTR*)pInsertStrings, /*data*/ NULL);
}
几乎一切都按预期进行。该事件会在事件日志中弹出,并包含我在调用
ReportEvent()
时发送的所有内容。
但是,我在通话中发送的文本字符串仅显示在
Details
弹出窗口的 Event Properties
窗格中。
我怎样才能便宜地将此文本放入
General
窗格中?
我知道调用
dwEventID
中的参数 ReportEvent()
控制着 General
窗格中的文本。但我知道可以通过其他方式控制此文本,但仍然不受消息文件的复杂性的影响。
你怎么能做到?
下面的程序显示了针对该问题的建议解决方案。该程序不使用 WINAPI 来访问事件日志,而是使用 .NET 函数。
#using <system.dll>
#using <mscorlib.dll>
#include <winsock2.h>
using namespace System;
using namespace System::Diagnostics;
int main()
{
String^ sSource = gcnew String("TestLog");
String^ sLog = gcnew String("Application");
String^ sEvent = gcnew String("Sample event message from EvenLogTest");
try
{
if (!EventLog::SourceExists(sSource))
EventLog::CreateEventSource(sSource, sLog);
}
catch (Exception^ e) {
MessageBox(nullptr, L"Run this program once as Administrator", L"EventLogTest", MB_OK | MB_SYSTEMMODAL | MB_ICONERROR);
exit(0);
}
EventLog::WriteEntry(sSource, sEvent);
}
该程序展示了完整的测试解决方案。第一次执行时,程序会在注册表中注册日志
TestLog
。此操作需要管理员权限。如果程序不是由管理员启动的,则会在 MessageBox
中显示相应的消息并退出。第一次管理员执行后的程序执行不需要任何权限,用于将更多事件插入日志中。
要在 Visual Studio 中编译此程序,属性->配置属性->高级->公共语言运行时支持必须设置为
.NET Framework Runtime Support (/clr)
。 因此,编译器使用 C++ 的 Common Language
版本,而不是本机 C++。这可能会导致 CLR 和本机 C++ 的混合并导致冲突。例如,#include <iostream>
会生成非致命编译错误,其功能最好用 .NET 函数替换。
由于语言复杂性以及需要管理员运行一次,建议的解决方案比原始程序更复杂。优点是它可以控制事件的
General
窗格中的文本。相比之下,原始程序要简单得多,但事件文本仅在 Details
窗格中可见,而 General
窗格显示一些难以控制的标准文本。