Модернизация журнала событий Windows для приложения Delphi 5 - PullRequest
4 голосов
/ 26 марта 2009

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

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

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

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

Ответы [ 4 ]

6 голосов
/ 14 мая 2015

Сводка: запись в журнал событий 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.

4 голосов
/ 26 марта 2009

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

  • Добавить "SvcMgr" к предложению использования
  • Используйте этот код для добавления вашего текстового сообщения и идентификационного номера (последний параметр в строках 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;
    
3 голосов
/ 26 марта 2009

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

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

    MyEventLog: TEventLogger;

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

    MyEventLog: = TEventLogger.Create ('MyApplication');

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

    MyEventLog.LogMessage ('MyApplication запущено.'), EVENTLOG_INFORMATION_TYPE);

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

    MyEventLog.Free;

Для регистрации приложения в журнале событий Windows необходимо выполнить другие действия, чтобы перед ним появлялось сообщение:

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

1 голос
/ 27 марта 2009

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

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

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

...