web-dev-qa-db-ja.com

Delphiを使用してWindowsイベントログに書き込む

DelphiアプリでWindowsイベントログに簡単に書き込む方法を教えてください。

TEventLoggerとReportEventの違いは何ですか? ReportEvent関数を使用するにはどうすればよいですか?

21
Kobus Smit

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を書き込む上記のイベントログ herehere および here

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 関数を前述のように使用することもできます here および here

簡単にするために単純なクラスを作成しました。これは 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 ローカルまたはリモートマシンのイベントログへのログエントリの書き込みをサポートします。リモートの例については、 John KasterのEDN記事 を参照してください。


メッセージファイルを作成する および イベントソースを登録するも必要になることに注意してください。ログメッセージは次のようなもので始まります。

ソースxxxxからのイベントID xxxの説明が見つかりません。このイベントを発生させるコンポーネントがローカルコンピューターにインストールされていないか、インストールが破損しています。ローカルコンピュータにコンポーネントをインストールまたは修復できます。

イベントが別のコンピューターで発生した場合、表示情報をイベントと共に保存する必要がありました。

イベントには次の情報が含まれていました。

1、メッセージファイルの作成方法の詳細については、 Finn Tolderlundのチュートリアル または Michael Hexの記事 を参照するか、既存のMCおよび RESに含まれているファイルを使用できます。 GitHubプロジェクト

2、DPRファイルにMessageFile.resを含めることにより、RESファイルをアプリケーションに埋め込みます。または、メッセージ用の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の[イベントログ]ウィンドウに書き込む場合は、 ここ を参照してください。

31
Kobus Smit