Подтвердить что ты не робот

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

Как мое приложение Delphi может легко записывать в журнал событий Windows?

В чем разница между TEventLogger и ReportEvent? Как использовать функцию ReportEvent?

4b9b3361

Ответ 1

Если вы пишете службу 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 Event Log, упомянутый здесь, здесь и здесь.

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 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 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 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. Для получения дополнительной информации о том, как создать файл сообщения, см. учебник Finn Tolderlund или статья Майкла Хекса или вы можете использовать существующий 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.