イベントログをCSV形式で出力するには?

解決


らりばど  2002-04-16 01:48:04  No: 805

こんにちわ。らりばどです。

WindowsNTおよびWindows2000で、イベントログに記録されている
内容をCSV形式に出力する方法を教えて下さい。
開発環境:Delphi6

実はAPI関数であるReadEventLog関数でできるとの情報は掴みまし
た。C言語のサンプルソースも見つけました。が、うまく移行でき
ずDelphiのソースを仕上げることができない状態です。

何かもっと良い方法が無いものかと思いカキコした次第です。
よろしくお願いします。


にしの  2002-04-16 03:03:47  No: 806

http://www2.big.or.jp/~osamu/Delphi/delphi-browse.cgi?index=013468
ここにサンプルがあります。

英語ですが、
http://www.jps.org/~wine/WinDoc/msdn/sdk/platforms/doc/sdk/win32/func/src/f71_10.htm
ここに、ReadEventLogの説明があります。


らりばど  2002-04-16 17:38:38  No: 807

>にしのさん

Delphi版のサンプルソースも見ることができて
助かります。
リンク先の記事を参考に試してみます。


らりばど  2002-04-18 01:34:14  No: 808

すみません、再度質問させて下さい。
にしのさんに教えてもらったサイトに別記事でログがありました。
http://leed.issp.u-tokyo.ac.jp/~takeuchi/delphi/browse.cgi?index=061955
こちらをベースにソースを構築しようとしましたが、値をうまく取得
することができません。
(そっくりそのままコピーしても問題は解消されませんでした。)

コンソールアプリケーションにて、
API(BackupEventLog)を利用したEVT形式でのデータ取得と、
API(ReadEventLog)を利用したCSV形式でのデータ取得が目的です。

API(BackupEventLog)は問題なく処理されますので、イベントログ
のオープン、クローズは問題ありません。

API(ReadEventLog)も問題なく処理されますが、その後データを表
示させようとした場合に、クラス例外が発生します。
しかしデバッカ上では、問題なく値が入っているように見えます。
※デバッカ上でマウスをその項目に重ねると値が見えます。
値の取得の仕方が悪いのでしょうか?
サンプルをそのままコピーしてもダメだったので、
別に悪いことろがあるのでは?と思っていますが
箇所を特定できません。

よろしくお願いします。

Function ReadEventLog(hEventLog:THandle; Flags:dword; RecordNo:dword; buf:Pointer; BufSize:dword; ReadBytes:dword; NextSize:dword) : BOOL;
stdcall; external 'advapi32.dll' name 'ReadEventLogA';

var hEventLog : THandle;
var Result : BOOL;
var LogMode : PChar;

const
  EVENTLOG_SEQUENTIAL_READ = $0001;
  EVENTLOG_SEEK_READ      = $0002;
  EVENTLOG_FORWARDS_READ  = $0004;
  EVENTLOG_BACKWARDS_READ  = $0008;
  CRLF = #13 + #10;

var
  lpBuf: Pointer;
  ReadFlags,
  RecordOffset,
  NumberOfByteRead,
  ByteRead,
  MinNumberOfBytesNeeded,
  BufLen: Cardinal;
  X: Char;
  PELR: TPELR;
  S: String;
  C: DWORD;

begin

  //イベントログのオープン処理

  //EVT形式でのデータ取得の場合、
  //API(BackupEventLog)を使ってデータ取得

  //以下、CSV形式でのデータ取得の場合
  begin
    ReadFlags := EVENTLOG_FORWARDS_READ or EVENTLOG_SEQUENTIAL_READ;
    ByteRead := 0;
    RecordOffset := 0;
    lpbuf := @X;
    NumberOfByteRead := 0;
    MinNumberOfBytesNeeded := 0;

    ReadEventLog(hEventLog,
                 ReadFlags,
                 RecordOffset,
                 lpBuf,
                 NumberOfByteRead,
                 ByteRead,
                 MinNumberOfBytesNeeded);

    BufLen := MinNumberOfBytesNeeded;
    NumberOfByteRead := BufLen;

    GetMem(lpBuf,BufLen);
    try
      ReadEventLog(hEventLog,
                   ReadFlags,
                   RecordOffset,
                   lpBuf,
                   NumberOfByteRead,
                   ByteRead,
                   MinNumberOfBytesNeeded);
      PELR := lpbuf;
      C := PELR^.EventID;    <---問題発生箇所
      S := IntToStr(C);
      writeln(S);
    except
      if Assigned(lpBuf) then FreeMem(lpBuf);
    end;
    FreeMem(lpBuf);
  end;

  //イベントのクローズ

end.


にしの  2002-04-18 02:29:11  No: 809

コンソールアプリケーションではないですが、こんな感じで出来ました。
ShowMessageのところを、Writelnにすれば同じだと思います。

procedure TForm1.Button3Click(Sender: TObject);
var
  hEventLog: THandle;
  e: TEventLogRecord;
  buf: PChar;
  ReadFlags, ByteRead, Size1, Size2: Cardinal;
  Res: BOOL;

  S: String;
  C: DWORD;
  PELR: PEventLogRecord;
begin
  ReadFlags := EVENTLOG_FORWARDS_READ or EVENTLOG_SEQUENTIAL_READ;

  hEventLog := OpenBackupEventLog(nil, PChar(Edit2.Text));

  while true do
  begin
    Size1 := 1;
    GetMem(buf, Size1);
    Res := ReadEventLog(
      hEventLog,
      ReadFlags,
      0,
      buf,
      Size1,
      ByteRead,
      Size2);
    if  (not Res)
    And (GetLastError <> ERROR_INSUFFICIENT_BUFFER) then Break;
    FreeMem(buf);
    buf := nil;

    Size1 := Size2;
    GetMem(buf, Size1);
    Res := ReadEventLog(
      hEventLog,
      ReadFlags,
      0,
      buf,
      Size1,
      ByteRead,
      Size2);
    if not Res then Break;

    PELR := PEventLogRecord(buf);

    C := PELR.EventID;
    S := IntToStr(C);

    ShowMessage(S);

    FreeMem(buf);
  end;
  FreeMem(buf);

  CloseEventLog(hEventLog);
end;


らりばど  2002-04-18 06:32:18  No: 810

>にしのさん

whileに入って1回目のReadEventLog関数でダメです。
どうやっても False が帰ってきます。
ソースはほぼそのままコピーしてみてもダメです。

hEventLog にはちゃんと値が入っています。
BackupEventlog関数が問題なく動くので大丈夫だろうと
思います。

なぜReadEventLog関数が返ってこなくなったのでしょうか。
API宣言も見直してみましたが、何か足りない宣言でも
あるのでしょうか?

ちなみに uses は SysUtils と Windows です。
もしかして不足しているのでしょうか?


にしの  2002-04-18 07:41:41  No: 811

あ、もしかして、関数の宣言しなおししています?
上の宣言、詳しく見ていませんでしたが、間違っています。

Function ReadEventLog(
  hEventLog:THandle; 
  Flags:dword; 
  RecordNo:dword; 
  buf:Pointer; 
  BufSize:dword; 
  ReadBytes:dword; 
  NextSize:dword) : BOOL;
stdcall; external 'advapi32.dll' name 'ReadEventLogA';

ではなく、

function ReadEventLog(
  hEventLog: THandle;
  dwReadFlags, 
  dwRecordOffset: DWORD;
  lpBuffer: Pointer; 
  nNumberOfBytesToRead: DWORD;
  var pnBytesRead, 
    pnMinNumberOfBytesNeeded: DWORD): BOOL; stdcall;
  external 'advapi32.dll' name 'ReadEventLogA';
です。
# 少しわかりやすく、引数1つずつに改行しました。

でもこの定義、Windows.pasにあるはずですが・・・。


らりばど  2002-04-19 07:32:51  No: 812

>にしのさん

ありがとうございます。
数字ばっかりですけど一覧が表示されるようになりました。

関数の宣言が重複していたのが原因のようでした。
最初、Windows.pas は記載していなかったのですが
途中で追記したのをそのままにしていたのが原因でした。

あと「ポインタ絡み」のところが知識として弱いことを
痛感しました。この件を参考に勉強します。

またこれから「ソース名の取得」など、日本語表示部分に
とりかかります。


※返信する前に利用規約をご確認ください。








  このエントリーをはてなブックマークに追加