在Windows事件日志中写入未找到Delphi事件ID

时间:2017-11-08 13:38:36

标签: windows delphi event-log

我正在用Delphi编写Windows的Service应用程序。在某些事件中,我将消息写入Windows EventLog。这样可行,但每个日志条目中都有以下文本:

  

无法找到源yyyyy的事件ID xxx的描述......

我不想要这个。

我做了什么:

  1. 使用以下内容生成ResouceEventlog.mc:

    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
    
    .
    
  2. 使用ResourceEventlog.mc

  3. 汇编mc.exe
  4. RecourceEventLog.rcbrcc32.exe编译为ResourceEventlog.res

  5. {$R RecourceEventlog.res}添加到我的服务应用程序的主单元

  6. AfterInstall事件中,我创建了一些注册表项:

    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
    
  7. 在我的服务应用程序中,我定义了一些常量并使用TService.LogEvent()将消息写入事件日志:

    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);
    
  8. 事件日志条目已成功创建,但无法找到"事件ID"文字仍然出现。

1 个答案:

答案 0 :(得分:2)

.mc文件中的所有邮件均未指定SeverityFacility。默认SeveritySuccess,位于SeverityName列表中,但默认FacilityApplication0xFFF),但不是在您的FacilityNames列表中。

消息的SeverityFacility号码作为存储在已编译消息资源中的最终资源ID号的一部分包含在内。这是必须在TService.LogMessage()参数中传递给ReportEvent()(由dwEventID包装)的数字,以便它可以找到正确的资源字符串。 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.

这也包含在MSDN支持中:

HOWTO: Troubleshooting the "Event Message Not Found" Message

  
      
  1. 确保将正确的ID传递给ReportEvent函数。
  2.         

    许多人认为.mc文件中的文字ID号是正确的ID。这不是那么,因为消息编译器将ID编号按位OR运算为LOWORD,并将严重性和设施位按位OR运算为HIWORD。应用程序应始终使用从消息编译器输出的头文件中的符号名称。

         

    验证.mc文件中的MessageIdTypedef =语句。一些示例.mc文件显示如何为类别ID定义MessageIDTypedef为WORD。但是,这会导致事件ID松开HIWORD。要解决此问题,请仅定义MessageIdTypedef =一次并将其设置为DWORD。

         

    还要确保MC -c命令行始终用于消息资源和头文件。 -c开关在消息ID的HIWORD中打开一个位。

mc.exe-c开关导致" 在所有消息ID中设置客户位(位28)。"

但是,您的Delphi常量并不考虑这种格式。

例如,您的.mc文件定义CALL_PROCESS MessageIDCode以上)0x2003Severity或{ {1}},分别使用FacilitySuccess=0x0。因此,Application=0xFFF的实际EventID是CALL_PROCESS(您可以通过使用任何资源查看器/编辑器工具查看已编译的消息资源来验证这一点。)

但是,您的Delphi代码将0x2FFF2003定义为CALL_PROCESS,这不是您需要传递给$00002003的正确数字!

这同样适用于您的所有其他消息EventID(LogMessage()LIC_INFO)。

邮件category identifierERR_UDP按原样使用,因此您的Delphi代码(MessageIDCAT_ALL)中的类别常量都很好

请改为尝试:

CAT_ERR

即使您修复了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; 文件以明确指定每封邮件的正确.mcSeverity值,也请确保您还考虑Delphi常量中的Customer位。

例如,如果您将每条消息的Facility设置为0x0,则正确的EventID将如下所示:

Facility

然后,如果您在错误消息上将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; 设置为Severity,则正确的EventID将如下所示:

Error

因此,正确定义EventID常量会使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; 是否可以在消息资源中找到它们有很大的不同。