Запись в Windows-Eventlog с Delphi Event-ID не найден

Я пишу приложение службы для Windows в Delphi. О некоторых событиях я пишу сообщения в Windows EventLog. Это работает, но в каждой записи журнала есть следующий текст:

Описание для идентификатора события xxx из источника yyyyy не может быть найдено...

Я не хочу этого

Что я сделал:

  1. создать ResouceEventlog.mc с этим содержанием:

    SeverityNames = (Success = 0x0: STATUS_SEVERITY_SUCCESS
                   Информационный =0x1:STATUS_SEVERITY_INFORMATIONAL
                   Предупреждение =0x2:STATUS_SEVERITY_WARNING
                   Ошибка =0x3:STATUS_SEVERITY_ERROR)
    
    FacilityNames=(System=0x0:FACILITY_SYSTEM
                   Продолжительность =0x2:FACILITY_RUNTIME
                   Столбики =0x3:FACILITY_STUBS
                   Ио =0x4:FACILITY_IO_ERROR_CODE)
    
    LanguageNames=(немецкий =0x407:MSG00407)
    
    MessageIdTypedef= СЛОВО
    
    MessageID=0x1
    Символическое = CAT_ALL
    Язык = Немецкий
    Allgemein,
    
    MessageID=0x2
    Символическое = CAT_CALL
    Язык = Немецкий
    Anruf,
    
    MessageID=0x3
    Символическое = CAT_LIC
    Язык = Немецкий
    Lizenzinformation,
    
    MessageID=0x4
    Символическое =CAT_INFO
    Язык = Немецкий
    Informationen,
    
    MessageID=0x5
    Символическое = CAT_ERR
    Язык = Немецкий
    Fehler,
    
    MessageIdTypedef=DWORD
    
    MessageID=0x1000
    Символическое =LIC_INFO
    Язык = Немецкий
    Lizenzinformationen,
    
    MessageID=0x1001
    Символическое =LIC_EXP
    Язык = Немецкий
    Lizenzinformationen,
    
    MessageID=0x2000
    Символическое =CALL_SiG
    Язык = Немецкий
    Anruf signalisieren,
    
    MessageID=0x2001
    Символическое =CALL_DBL
    Язык = Немецкий
    Анруф Беретс Эрфаст,
    
    MessageID=0x2002
    Символическое =CALL_CAPI
    Язык = Немецкий
    Анруф КАПИ,
    
    MessageID=0x2003
    Символическое =CALL_PROCESS
    Язык = Немецкий
    Анруф Верарбайтен,
    
    MessageID=0x3000
    Символическое =ERR_CAPI
    Язык = Немецкий
    Capi Fehler,
    
    MessageID=0x3001
    Символическое =ERR_PATH
    Язык = Немецкий
    Speicherpfad kann nicht erstellt weren,
    
    MessageID=0x3002
    Символическое =ERR_NOCAPI
    Язык = Немецкий
    Keine CAPI gefunden,
    
    MessageID=0x3003
    Символическое = ERR_UDP
    Язык = Немецкий
    UDP_Empfangs_Port ist 0,
  2. компилировать ResourceEventlog.mc с mc.exe

  3. компилировать RecourceEventLog.rc с brcc32.exe в ResourceEventlog.res

  4. добавлять {$R RecourceEventlog.res} в основной блок моего приложения службы

  5. в AfterInstall Событие, я создаю некоторые записи реестра:

    Редактор реестра Windows, версия 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
  6. в моем приложении службы я определяю некоторые константы и использую 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);
    

Запись журнала событий успешно создана, но текст "Идентификатор события не найден" по-прежнему отображается.

1 ответ

Ни одно из ваших сообщений в .mc файл задают Severity или же Facility, По умолчанию Severity является Success, который находится в вашем SeverityName список, но по умолчанию Facility является Application (0xFFF), чего нет в вашем FacilityNames список.

Сообщение Severity а также Facility номера включаются как часть окончательного идентификационного номера ресурса, который хранится в ресурсе скомпилированного сообщения. Это число, которое необходимо передать ReportEvent() (завернутый TService.LogMessage()) в своем dwEventID параметр, чтобы он мог найти правильную строку ресурса. Точный формат этого параметра задокументирован в MSDN:

Идентификаторы событий

 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
+---+-+-+-----------------------+-------------------------------+
| Сева |C|R| Объект | Код |
+---+-+-+-----------------------+-------------------------------+

Sev

    Строгость. Серьезность определяется следующим образом:

        00 - успех
        01 - Информационный
        10 - Предупреждение
        11 - ошибка

С

    Клиент немного. Этот бит определяется следующим образом:

        0 - системный код
        1 - код клиента

р

    Зарезервированный бит.

объект

    Код объекта. Это значение может быть FACILITY_NULL.

Код

    Код состояния объекта.

Это также покрывается поддержкой MSDN:

HOWTO: Устранение неполадок с сообщением "Событие не найдено"

  1. Убедитесь, что правильный идентификатор передан в функцию ReportEvent.

Многие считают, что буквальный идентификационный номер, найденный в файле.mc, является правильным идентификатором. Это не так, потому что компилятор сообщений поразрядно ИЛИ вводит номер идентификатора в LOWORD, а побитовый ИЛИ устанавливает биты серьезности и обслуживания в HIWORD. Приложение всегда должно использовать символическое имя в заголовочном файле, который выводится из компилятора сообщений.

Проверьте оператор MessageIdTypedef= в файле.mc. Некоторые примеры файлов.mc показывают, как определить MessageIDTypedef для WORD для идентификаторов категорий. Однако это приводит к тому, что идентификаторы событий теряют HIWORD. Чтобы исправить эту проблему, определите MessageIdTypedef= только один раз и установите для него значение DWORD.

Также убедитесь, что командная строка MC -c последовательно используется для ресурсов сообщений и заголовочного файла. Ключ -c немного включается в HIWORD идентификатора сообщения.

-c переключатель mc.exe заставляет его " устанавливать бит клиента (бит 28) во всех идентификаторах сообщений ".

Однако ваши константы Delphi не учитывают этот формат.

Например, ваш .mc файл определяет CALL_PROCESS с MessageID (Code выше) из 0x2003 и нет Severity или же Facility, так Success=0x0 а также Application=0xFFF используются соответственно. Таким образом, фактический Event ID для CALL_PROCESS является 0x2FFF2003 (Вы можете убедиться в этом, посмотрев ресурс скомпилированного сообщения с помощью любого средства просмотра / редактирования ресурсов).

Но ваш код Delphi определяет CALL_PROCESS как $00002003, который НЕ является правильным номером, на который нужно перейти LogMessage()!

То же самое относится ко всем другим сообщениям Event ID (LIC_INFO через ERR_UDP).

MessageID идентификатора категории сообщения используется как есть, поэтому эти константы категории в вашем коде Delphi (CAT_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;

Даже если вы исправите .mc файл, чтобы явно указать правильный Severity а также Facility значения для каждого сообщения, убедитесь, что вы также учитываете бит клиента в ваших константах Delphi.

Например, если вы установите каждое сообщение Facility до 0x0 правильные идентификаторы событий будут выглядеть так:

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 в Error в сообщениях об ошибках правильные идентификаторы событий будут выглядеть так:

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;

Таким образом, правильное определение констант Event ID делает БОЛЬШУЮ разницу в том, ReportEvent() можете найти их в ресурсе сообщений.

Другие вопросы по тегам