I'm trying to cheat with the EventLog in a C++ application. I have no message file; I simply use RegisterEventSource()
and ReportEvent()
in a sequence.
#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);
}
Almost everything works as expected. The event pops up in the EventLog and contains all the pieces I have sent in in the call to ReportEvent()
.
However, the text string I sent in the call only shows up in the Details
pane of the Event Properties
popup.
How can I cheaply get this text into the General
pane?
I understand that the parameter dwEventID
in the call to ReportEvent()
controls the text in the General
pane. But I know it is possible to control this text in some other way, still free from the complexity of the message file.
How can you do it?
The program below shows a proposed solution for the problem. Instead of using WINAPI for access to the Event Log, the program uses .NET functions.
#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);
}
The program shows a complete test solution. At the first execution, the program installs in the registry the log source TestLog
under Application
. This operation requires administrator privileges. If the program is not started by the administrator, it displays the corresponding message in a MessageBox
and quits. Subsequent program executions do not require any privileges and are used to insert further events into the log.
To compile this program in Visual Studio, the parameter Properties->Configuration Properties->Advanced->Common Language Runtime Support must be set to .NET Framework Runtime Support (/clr)
. Consequently, the compiler uses the Common Language
version of C++ rather than the native C++. This may lead to a mix of CLR and native C++ and cause collisions. As an example, #include <iostream>
generates non-stopping compilation errors, and its functionality should preferably be replaced with equivalent .NET functions.
The proposed solution is more complex than the original program, both due to the language complications and the need to run it once by the administrator. The advantage is that it provides control over the text in the event's General
pane. By comparison, the original program is much simpler, but the event text is only visible in the Details
pane, while the General
pane shows some hard to control standard text.
I would not consider creating my own message file (.NET functions do use a message file). It's unnecessary and complex. There is a reason why the .NET implementation has removed this burden from the user.