问题
I am writing a Service application for Windows in Delphi. On some events I write messages to the Windows EventLog. That works, but there is the following text in every log entry:
The description for Event ID xxx from source yyyyy cannot be found...
I don't want this.
What I have done:
generate an ResouceEventlog.mc with this content:
SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS Informational=0x1:STATUS_SEVERITY_INFORMATIONAL Warning=0x2:STATUS_SEVERITY_WARNING Error=0x3:STATUS_SEVERITY_ERROR ) FacilityNames=(System=0x0:FACILITY_SYSTEM Runtime=0x2:FACILITY_RUNTIME Stubs=0x3:FACILITY_STUBS Io=0x4:FACILITY_IO_ERROR_CODE ) LanguageNames=(German=0x407:MSG00407) MessageIdTypedef=WORD MessageID=0x1 Symbolicname=CAT_ALL Language=German Allgemein . MessageID=0x2 Symbolicname=CAT_CALL Language=German Anruf . MessageID=0x3 Symbolicname=CAT_LIC Language=German Lizenzinformation . MessageID=0x4 Symbolicname=CAT_INFO Language=German Informationen . MessageID=0x5 Symbolicname=CAT_ERR Language=German Fehler . MessageIdTypedef=DWORD MessageID=0x1000 Symbolicname=LIC_INFO Language=German Lizenzinformationen . MessageID=0x1001 Symbolicname=LIC_EXP Language=German Lizenzinformationen . MessageID=0x2000 Symbolicname=CALL_SiG Language=German Anruf signalisieren . MessageID=0x2001 Symbolicname=CALL_DBL Language=German Anruf bereits erfasst . MessageID=0x2002 Symbolicname=CALL_CAPI Language=German Anruf an CAPI . MessageID=0x2003 Symbolicname=CALL_PROCESS Language=German Anruf verarbeiten . MessageID=0x3000 Symbolicname=ERR_CAPI Language=German Capi Fehler . MessageID=0x3001 Symbolicname=ERR_PATH Language=German Speicherpfad kann nicht erstellt weren . MessageID=0x3002 Symbolicname=ERR_NOCAPI Language=German Keine CAPI gefunden . MessageID=0x3003 Symbolicname=ERR_UDP Language=German UDP_Empfangs_Port ist 0 .
Compile
ResourceEventlog.mc
withmc.exe
Compile
RecourceEventLog.rc
withbrcc32.exe
toResourceEventlog.res
Add
{$R RecourceEventlog.res}
to the main unit of my service applicationin the
AfterInstall
event, I create some Registry entries:Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application\Anrufmonitor] "EventMessageFile"="C:\\AM\\AMService.exe" "CategoryMessageFile"="C:\\AM\\AMService.exe" "CategoryCount"=dword:00000005 "TypesSupported"=dword:00000007
in my Service application I define some constants and use
TService.LogEvent()
to write messages to the eventlog:const CAT_ALL :WORD =$1; CAT_CALL :WORD =$2; CAT_LIC :WORD =$3; CAT_INFO :WORD =$4; CAT_ERR :WORD =$5; LIC_INFO :DWORD =$00001000; LIC_EXP :DWORD =$00001001; CALL_SIG :DWORD =$00002000; CALL_DBL :DWORD =$00002001; CALL_CAPI :DWORD =$00002002; CALL_PROCESS :DWORD =$00002003; ERR_CAPI :DWORD =$00003000; ERR_PATH :DWORD =$00003001; ERR_NOCAPI :DWORD =$00003002; ERR_UDP :DWORD =$00003003; ... LogMessage('test an eventlog-entry', EVENTLOG_INFORMATION_TYPE, CAT_CALL, CALL_PROCESS);
The eventlog entry is created successfully, but the "Event ID cannot be found" text still appears.
回答1:
None of your messages in the .mc
file are specifying a Severity
or Facility
. The default Severity
is Success
, which is in your SeverityName
list, but the default Facility
is Application
(0xFFF
), which is not in your FacilityNames
list.
A message's Severity
and Facility
numbers are included as part of the final resource ID number that is stored in the compiled message resource. That is the number which must be passed to ReportEvent() (wrapped by TService.LogMessage()
) in its dwEventID
parameter so it can find the correct resource string. The exact format of that parameter is documented on MSDN:
Event Identifiers
3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +---+-+-+-----------------------+-------------------------------+ |Sev|C|R| Facility | Code | +---+-+-+-----------------------+-------------------------------+ Sev Severity. The severity is defined as follows: 00 - Success 01 - Informational 10 - Warning 11 - Error C Customer bit. This bit is defined as follows: 0 - System code 1 - Customer code R Reserved bit. Facility Facility code. This value can be FACILITY_NULL. Code Status code for the facility.
This is also covered on MSDN Support:
HOWTO: Troubleshooting the "Event Message Not Found" Message
- Make sure the correct ID is passed to the ReportEvent function.
Many think that the literal ID number found in the .mc file is the correct ID. This is not so because the message compiler bitwise ORs the ID number into the LOWORD and bitwise ORs the severity and facility bits into the HIWORD. An application should always use the symbolic name in the header file that is output from the message compiler.
Verify the MessageIdTypedef= statement in the .mc file. Some example .mc files show how to define the MessageIDTypedef to WORD for Category IDs. However, this causes Event IDs to loose the HIWORD. To correct this issue, define MessageIdTypedef= only once and set it to DWORD.
Also be sure that the MC -c command line is consistently used for the message resources and header file. The -c switch turns on a bit in the HIWORD of the message ID.
The -c
switch of mc.exe causes it to "set the customer bit (bit 28) in all message IDs."
However, your Delphi constants are not accounting for this format.
For example, your .mc
file defines CALL_PROCESS
with a MessageID
(the Code
above) of 0x2003
and no Severity
or Facility
, so Success=0x0
and Application=0xFFF
are used, respectively. Thus, the actual EventID for CALL_PROCESS
is 0x2FFF2003
(you can verify this by looking at the compiled message resource with any Resource viewer/editor tool).
But, your Delphi code is defining CALL_PROCESS
as $00002003
, which is NOT the correct number that you need to pass to LogMessage()
!
The same applies to all of your other message EventIDs (LIC_INFO
through ERR_UDP
).
The MessageID
of a message's category identifier is used as-is, so those category constants in your Delphi code (CAT_ALL
through CAT_ERR
) are fine.
Try this instead:
const
CAT_ALL :WORD =$1;
CAT_CALL :WORD =$2;
CAT_LIC :WORD =$3;
CAT_INFO :WORD =$4;
CAT_ERR :WORD =$5;
LIC_INFO :DWORD =$2FFF1000;
LIC_EXP :DWORD =$2FFF1001;
CALL_SIG :DWORD =$2FFF2000;
CALL_DBL :DWORD =$2FFF2001;
CALL_CAPI :DWORD =$2FFF2002;
CALL_PROCESS :DWORD =$2FFF2003;
ERR_CAPI :DWORD =$2FFF3000;
ERR_PATH :DWORD =$2FFF3001;
ERR_NOCAPI :DWORD =$2FFF3002;
ERR_UDP :DWORD =$2FFF3003;
Even if you fix your .mc
file to explicitly specify correct Severity
and Facility
values for each message, make sure you also account for the Customer bit in your Delphi constants.
For example, if you set each message's Facility
to 0x0, the correct EventIDs would look like this:
const
CAT_ALL :WORD =$1;
CAT_CALL :WORD =$2;
CAT_LIC :WORD =$3;
CAT_INFO :WORD =$4;
CAT_ERR :WORD =$5;
LIC_INFO :DWORD =$20001000;
LIC_EXP :DWORD =$20001001;
CALL_SIG :DWORD =$20002000;
CALL_DBL :DWORD =$20002001;
CALL_CAPI :DWORD =$20002002;
CALL_PROCESS :DWORD =$20002003;
ERR_CAPI :DWORD =$20003000;
ERR_PATH :DWORD =$20003001;
ERR_NOCAPI :DWORD =$20003002;
ERR_UDP :DWORD =$20003003;
And then, if you set the Severity
to Error
on the error messages, the correct EventIDs would look like this:
const
CAT_ALL :WORD =$1;
CAT_CALL :WORD =$2;
CAT_LIC :WORD =$3;
CAT_INFO :WORD =$4;
CAT_ERR :WORD =$5;
LIC_INFO :DWORD =$20001000;
LIC_EXP :DWORD =$20001001;
CALL_SIG :DWORD =$20002000;
CALL_DBL :DWORD =$20002001;
CALL_CAPI :DWORD =$20002002;
CALL_PROCESS :DWORD =$20002003;
ERR_CAPI :DWORD =$E0003000;
ERR_PATH :DWORD =$E0003001;
ERR_NOCAPI :DWORD =$E0003002;
ERR_UDP :DWORD =$E0003003;
So, defining the EventID constants correctly makes a BIG difference in whether ReportEvent()
can find them in the message resource.
来源:https://stackoverflow.com/questions/47181193/write-in-windows-eventlog-with-delphi-event-id-not-found