Модернизация журнала событий Windows в приложении Delphi 5

Я ищу (довольно безболезненный) способ добавления поддержки журнала событий приложений Windows в небольшое устаревшее приложение Delphi 5. Мы просто хотим, чтобы он регистрировал, когда он запускается, выключается, не может подключиться к базе данных и т. Д.

Некоторые из решений / компонентов, которые я видел, похоже, предполагают, что нам нужно создать ресурсную DLL, на которую будет ссылаться средство просмотра журнала событий Windows при попытке прочитать наши «записи». Хотя это не кажется слишком обременительным, я полагаю, что нужно иметь в виду еще кое-что, если / когда мы продолжим разработку приложения в будущем - нам нужно будет поддерживать эту DLL в актуальном состоянии.

В какой-то момент в будущем мы захотим превратить приложение в службу, вероятно, написанную на D2007.

Так может ли кто-нибудь порекомендовать подходящий маршрут для добавления событий в журнал событий в D5? Я ищу конкретные комментарии «мы использовали это, и это было нормально», а не трал Google (что я могу сделать сам!). Бесплатные или платные, правда не против - но кое-что то, что я смогу перейти на D2007 в будущем, очень важно.


person robsoft    schedule 26.03.2009    source источник


Ответы (4)


Резюме: запись в журнал событий Windows с помощью Delphi


Если вы пишете службу Windows и вам нужно записать в журнал событий Windows на локальном компьютере, вы можете вызвать TService. LogMessage, как упоминалось здесь.

//TMyTestService = class(TService)

procedure TMyTestService.ServiceStart(Sender: TService; var Started: Boolean);
begin
  LogMessage('This is an error.');
  LogMessage('This is another error.', EVENTLOG_ERROR_TYPE);
  LogMessage('This is information.', EVENTLOG_INFORMATION_TYPE);
  LogMessage('This is a warning.', EVENTLOG_WARNING_TYPE);
end;

Для любого другого типа приложений вы можете использовать SvcMgr. TEventLogger недокументированный вспомогательный класс для TService для записи журнала событий Windows на локальном компьютере, как упоминалось здесь, здесь и здесь.

uses
  SvcMgr;

procedure TForm1.EventLoggerExampleButtonClick(Sender: TObject);
begin
  with TEventLogger.Create('My Test App Name') do
  begin
    try
      LogMessage('This is an error.');
      LogMessage('This is another error.', EVENTLOG_ERROR_TYPE);
      LogMessage('This is information.', EVENTLOG_INFORMATION_TYPE);
      LogMessage('This is a warning.', EVENTLOG_WARNING_TYPE);
    finally
      Free;
    end;
  end;
end;

Вы также можете использовать Windows API ReportEvent, как упомянуто здесь и здесь.

Чтобы упростить задачу, я создал простой класс, он доступен на GitHub.

//----------------- EXAMPLE USAGE: ---------------------------------

uses
  EventLog;

procedure TForm1.EventLogExampleButtonClick(Sender: TObject);
begin
  TEventLog.Source := 'My Test App Name';

  TEventLog.WriteError('This is an error.');
  TEventLog.WriteInfo('This is information.');
  TEventLog.WriteWarning('This is a warning.');
end;

//------------------------------------------------------------------


unit EventLog;

interface

type
  TEventLog = class
  private
    class procedure CheckEventLogHandle;
    class procedure Write(AEntryType: Word; AEventId: Cardinal; AMessage: string); static;
  public
    class var Source: string;
    class destructor Destroy;

    class procedure WriteInfo(AMessage: string); static;
    class procedure WriteWarning(AMessage: string); static;
    class procedure WriteError(AMessage: string); static;

    class procedure AddEventSourceToRegistry; static;
  end;

threadvar EventLogHandle: THandle;

implementation

uses Windows, Registry, SysUtils;

class destructor TEventLog.Destroy;
begin
  if EventLogHandle > 0 then
  begin
    DeregisterEventSource(EventLogHandle);
  end;
end;

class procedure TEventLog.WriteInfo(AMessage: string);
begin
  Write(EVENTLOG_INFORMATION_TYPE, 2, AMessage);
end;

class procedure TEventLog.WriteWarning(AMessage: string);
begin
  Write(EVENTLOG_WARNING_TYPE, 3, AMessage);
end;

class procedure TEventLog.WriteError(AMessage: string);
begin
  Write(EVENTLOG_ERROR_TYPE, 4, AMessage);
end;

class procedure TEventLog.CheckEventLogHandle;
begin
  if EventLogHandle = 0 then
  begin
   EventLogHandle := RegisterEventSource(nil, PChar(Source));
  end;
  if EventLogHandle <= 0 then
  begin
    raise Exception.Create('Could not obtain Event Log handle.');
  end;
end;

class procedure TEventLog.Write(AEntryType: Word; AEventId: Cardinal; AMessage: string);
begin
  CheckEventLogHandle;
  ReportEvent(EventLogHandle, AEntryType, 0, AEventId, nil, 1, 0, @AMessage, nil);
end;

// This requires admin rights. Typically called once-off during the application's installation
class procedure TEventLog.AddEventSourceToRegistry;
var
  reg: TRegistry;
begin
  reg := TRegistry.Create;
  try
    reg.RootKey := HKEY_LOCAL_MACHINE;
    if reg.OpenKey('\SYSTEM\CurrentControlSet\Services\Eventlog\Application\' + Source, True) then
    begin
      reg.WriteString('EventMessageFile', ParamStr(0)); // The application exe's path
      reg.WriteInteger('TypesSupported', 7);
      reg.CloseKey;
    end
    else
    begin
      raise Exception.Create('Error updating the registry. This action requires administrative rights.');
    end;
  finally
    reg.Free;
  end;
end;

initialization

TEventLog.Source := 'My Application Name';

end.

ReportEvent поддерживает запись записи в журнал событий локального или удаленного компьютера. Удаленный пример см. В статье Джона Кастера о EDN.


Обратите внимание, что вам также потребуется создать файл сообщения и зарегистрируйте источник события в противном случае все сообщения журнала будут начинаться примерно так:

Описание для события с идентификатором xxx из источника xxxx не найдено. Либо компонент, вызывающий это событие, не установлен на вашем локальном компьютере, либо установка повреждена. Вы можете установить или отремонтировать компонент на локальном компьютере.

Если событие возникло на другом компьютере, отображаемую информацию нужно было сохранить вместе с событием.

Следующая информация была включена в мероприятие:

1. Для получения дополнительной информации о том, как создать файл сообщения, см. руководство Финна Толдерлунда или Майкла Хекса или вы можете использовать существующий MC и RES файл, включенный в проект GitHub.

2. Вставьте файл RES в свое приложение, включив MessageFile.res в свой DPR-файл. В качестве альтернативы вы можете создать dll для сообщений.

program MyTestApp;

uses
  Forms,
  FormMain in 'FormMain.pas' {MainForm},
  EventLog in 'EventLog.pas';

{$R *.res}
{$R MessageFile\MessageFile.res}

begin
  Application.Initialize;

3. Для однократной регистрации требуются права администратора на запись в реестр, поэтому обычно это делается в процессе установки вашего приложения.

//For example
AddEventSourceToRegistry('My Application Name', ParamStr(0));
//or
AddEventSourceToRegistry('My Application Name', 'C:\Program Files\MyApp\Messages.dll');

//--------------------------------------------------

procedure AddEventSourceToRegistry(ASource, AFilename: string);
var
  reg: TRegistry;
begin
  reg := TRegistry.Create;
  try
    reg.RootKey := HKEY_LOCAL_MACHINE;
    if reg.OpenKey('\SYSTEM\CurrentControlSet\Services\Eventlog\Application\' + ASource, True) then
    begin
      reg.WriteString('EventMessageFile', AFilename);
      reg.WriteInteger('TypesSupported', 7);
      reg.CloseKey;
    end
    else
    begin
      raise Exception.Create('Error updating the registry. This action requires administrative rights.');
    end;
  finally
    reg.Free;
  end;
end;

Если вам требуется ведение журнала событий Windows и другие требования к ведению журнала, вы также можете использовать платформы ведения журналов, такие как log4d и TraceTool


См. здесь, если вы хотите записать в окно журнала событий в Delphi IDE.

person Kobus Smit    schedule 14.05.2015

Для простой регистрации событий в D5 я использовал следующий код для добавления сообщений в журнал приложений.

  • Добавьте "SvcMgr" в раздел uses
  • Используйте этот код, чтобы добавить текстовое сообщение и идентификационный номер (последний параметр в строках LogMessage)

    with TEventLogger.create('My Application Name') do
    begin
      try
        LogMessage('Information Message!', EVENTLOG_INFORMATION_TYPE, 0, 1);
        LogMessage('Error Message!', EVENTLOG_ERROR_TYPE, 0, 2);
        LogMessage('Warning Message!', EVENTLOG_WARNING_TYPE, 0, 3);
        LogMessage('Audit Success Message!', EVENTLOG_AUDIT_SUCCESS, 0, 4);
        LogMessage('Audit Failure Message!', EVENTLOG_AUDIT_FAILURE, 0, 5);
      finally
        free;
      end;
    end;
    
person Peter McMinn    schedule 26.03.2009
comment
Спасибо, Питер - получилось удовольствие. Я просто прикидываю, что мне нужно делать с реестром и библиотеками ресурсов, чтобы все было чисто и аккуратно. Привет, Роб - person robsoft; 26.03.2009
comment
Не могли бы вы сказать, какая библиотека Windows содержит эти функции? Я действительно сомневаюсь, что добавление всего блока - разумная идея !!! использовать только несколько !!! функции внутри него ... Это advapi32.dll или winnt.dll ... или что? Заранее спасибо ... - person HX_unbanned; 08.09.2010

Я использую для этого стандартный VCL в Delphi 6, я не могу сказать, доступно ли это в Delphi 5. Попробуйте сами и сообщите нам, есть ли это в D5.

  1. Объявите глобальную переменную / форму типа TEventLogger. Это объявлено в модуле SvcMgr, поэтому его нужно будет добавить в ваш список использования. Если это обычное приложение (т.е. не служба), убедитесь, что SvcMgr добавлен после модуля Forms.

    MyEventLog: TEventLogger;

  2. Создайте экземпляр регистратора.

    MyEventLog: = TEventLogger.Create ('Мое приложение');

  3. Для записи в журнал событий:

    MyEventLog.LogMessage ('Мое приложение запущено.'), EVENTLOG_INFORMATION_TYPE);

  4. Не забудьте отпустить его в конце:

    MyEventLog.Free;

Есть и другие вещи, которые вам нужно сделать, чтобы зарегистрировать приложение в журнале событий Windows, чтобы перед ним появлялось сообщение без этого:

Не удалось найти описание для события с кодом (1000) в источнике (Microsoft Internet Explorer). На локальном компьютере может не быть необходимой информации реестра или файлов DLL сообщений для отображения сообщений с удаленного компьютера. Следующая информация является частью мероприятия:

person J__    schedule 26.03.2009
comment
Спасибо - между этим и ответом Питера МакМинна я пошел. Я вернусь и опубликую обновление с некоторой информацией о настройке DLL реестра / ресурсов, как только у меня все заработает. Еще раз спасибо! - person robsoft; 26.03.2009

Благодаря ответам J и Питера мой код сразу же записывался в журнал событий. Есть еще кое-что, что нужно сделать, особенно если вы хотите, чтобы ваши события отображались «красиво» в журнале событий без стандартного сообщения Windows о невозможности найти описание (согласно нижней части J пост).

Я выполнил советы здесь, чтобы сделал подходящую DLL и занес ее в реестр, и очень быстро со всем разобрался.

Согласно вопросу, все это было в Delphi5, но я не видел ничего, что заставляет меня думать, что это также не будет работать в D2007.

person robsoft    schedule 27.03.2009
comment
Я принял это как свой ответ просто потому, что он завершает ответ Дж. И Питера и связывает с другими частями, которые вам нужно сделать. Я не собираюсь получать от этого репутацию :-) - person robsoft; 21.04.2009