Mam's WebSite
建築CGパース住宅CGパース

Mamの覚書Q&A検索

トップページMamの覚書Q&A検索Delphi(API)⇒Q&A


大項目:「 Delphi 」 - 中項目:「 API 」

「 イベントログを読む 」

Windowsのイベントログを読む


回答

ソース

unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Vcl.ComCtrls;
 
type
  TForm1 = class(TForm)
    Button2: TButton;
    ProgressBar1: TProgressBar;
    procedure Button2Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;
 
type
  // Internal structure for event logs
  PEVENTLOGRECORD = ^EVENTLOGRECORD;
  EVENTLOGRECORD = packed record
    Length : DWORD;
    Reserved : DWORD;
    RecordNumber : DWORD;
    TimeGenerated : DWORD;
    TimeWritten : DWORD;
    EventID : DWORD;
    EventType : WORD;
    NumStrings : WORD;
    EventCategory : WORD;
    ReservedFlags : WORD;
    ClosingRecordNumber : DWORD;
    StringOffset : DWORD;
    UserSidLength : DWORD;
    UserSidOffset : DWORD;
    DataLength : DWORD;
    DataOffset : DWORD;
    // Then follows Variant Area .....
    // TCHAR SourceName[]
    // TCHAR Computername[]
    // SID   UserSid
    // TCHAR Strings[]
    // BYTE  Data[]
    // CHAR  Pad[]
    // DWORD Length;
  end;
 
  TEventLogRecord =EVENTLOGRECORD;
 
function TimeGeneratedToDateTime(aTimeGenerated: DWORD): TDateTime;
 
const
  EVENTLOG_SEQUENTIAL_READ    = 1;
  EVENTLOG_SEEK_READ          = 2;
  EVENTLOG_FORWARDS_READ      = 4;
  EVENTLOG_BACKWARDS_READ     = 8;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
function TimeGeneratedToDateTime(aTimeGenerated: DWORD): TDateTime;
const
  SecondPerDay = 60 * 60 * 24; //一日の秒数
begin
  Result := EncodeDate(1970,1,1) + EncodeTime(9,0,0,0);
  Result := ((Result * SecondPerDay) + aTimeGenerated) / SecondPerDay;
end;
 

 
procedure TForm1.Button2Click(Sender: TObject);
const
  //最新のログから順次読み込む
  READ_FLAG= EVENTLOG_SEQUENTIAL_READ or EVENTLOG_BACKWARDS_READ;
var
  eLogHandle: THandle;
  logCount: DWORD;
  i: Integer;
  eventID: Integer;
  pBuf: PEventLogRecord;
  bufSize: Integer;
  readNum, readNeed: DWORD;
  lastLogOn: TDateTime;
  lastLogOut: TDateTime;
  stl:TStringList;
 
  st,st2:string;
 

  lpSID: Pointer;
 
  szAccount, szDomain: array[0..MAX_PATH] of Char;
  dwAccountSize, dwDomainSize: DWORD;
  peUse: Cardinal;
 
  filename:string;
 

begin
  //システムログのオープン
  //eLogHandle := OpenEventLog(nil, 'System');
 
  //セキュリティログのオープン
  eLogHandle := OpenEventLog(nil, 'Security');
 
  stl:=TStringList.Create;
 
  stl.Add('種類,日付,時刻,ソース,分類,イベント,ユーザー,コンピューター');
 
  //クリア
  lastLogOn := 0;
  lastLogOut := 0;
  //Memo1.Lines.Clear;
 
  //ログが開けた場合に
  if eLogHandle > 0 then
  begin
    //ログ数を取得
    if not GetNumberOfEventLogRecords(eLogHandle, logCount) then
      logCount := 100000;
    ProgressBar1.Min:=0;
    ProgressBar1.Max:=logCount;
    ProgressBar1.Position:=0;
 
    //メモリ確保
    bufSize := SizeOf(TEventLogRecord);
    pBuf := AllocMem(bufSize);
 
    for i := 1 to logCount do
    begin
      {読み込み}
      //if not ReadEventLog(eLogHandle, READ_FLAG,
      //        logCount - 1, pBuf, bufSize, readNum, readNeed) then
      if not ReadEventLog(eLogHandle, READ_FLAG,
              logCount - 1, pBuf, 1, readNum, readNeed) then
 
      begin
       if GetLastError = ERROR_INSUFFICIENT_BUFFER then
       begin
         //メモリの再割り当て
         bufSize := readNeed;
         ReallocMem(pBuf, bufSize);
 
         if not ReadEventLog(eLogHandle, READ_FLAG,
             logCount - 1, pBuf, readNeed, readNum, readNeed) then
         begin
           //失敗
           Break;
         end;
       end
       else begin
         //失敗
         Break;
       end;
      end;
 
      st:='';
 
      //監査の成功8か失敗16か
      if pBUf^.EventType=1 then
        st:=st+'エラー,'
      else if pBUf^.EventType=2 then
        st:=st+'警告,'
      else if pBUf^.EventType=4 then
        st:=st+'情報,'
      else if pBUf^.EventType=8 then
        st:=st+'成功の監査,'
      else if pBUf^.EventType=16 then
        st:=st+'失敗の監査,'
      else
        st:=st+',';
 
      //日付
      lastLogOn := TimeGeneratedToDateTime(pBuf^.TimeGenerated);
      st:=st+FormatDateTime('yyyy/mm/dd', lastLogOn)+',';
      //時刻
      st:=st+FormatDateTime('hh:nn:ss', lastLogOn)+',';
 
      //ソース
      //st:=st+'Security,';
      st:=st+ StrPas(PChar(DWORD(pBuf)+sizeof(EVENTLOGRECORD)))+',';
 
      //分類
      st2:=PChar(DWORD(pBuf)+pBuf^.StringOffset);
      st:=st+st2+',';
 

      //イベントID
      eventID := pBuf^.EventID AND $FFFF;
      st:=st+Inttostr(eventID)+',';
 
      //ユーザー名
      lpSID:= pointer(DWORD(pBuf)+pBuf^.UserSidOffset);
      if (pBuf^.UserSidLength > 0) then
      begin
        dwAccountSize:= MAX_PATH;
        dwDomainSize:= MAX_PATH;
        if (not LookupAccountSid(nil, lpSID, szAccount, dwAccountSize,
                                 szDomain, dwDomainSize, peUse)) then
          raise Exception.Create(SysErrorMessage(GetLastError()));
 
        //Domain:= StrPas(szDomain);
        //Account:= StrPas(szAccount);
        st2:=szAccount;
      end;
      st:=st+st2+',';
 
      //コンピューター名
      st:=st+
        StrPas(
          PChar
          (
            DWORD(pBuf)+SizeOf(EVENTLOGRECORD)+
              lstrlen(PChar(DWORD(pBuf)+SizeOf(EVENTLOGRECORD)))+10
          )
        );
 
      stl.Add(st);
 
      ProgressBar1.Position:=ProgressBar1.Position+1;
    end;
 
    //Memo1.Lines.Add('最終ログイン:' + FormatDateTime('yyyy/mm/dd hh:nn:ss', lastLogOn));
    //Memo1.Lines.Add('最終ログオフ:' + FormatDateTime('yyyy/mm/dd hh:nn:ss', lastLogOut));
 
    //メモリ開放
    FreeMem(pBuf);
    //ログを閉じる
    CloseEventLog(eLogHandle);
 
  end;
 
  //memo1.Lines.Assign(stl);
 
  filename:=FormatDateTime('yyyymmddhhnnss',now())+'.csv';
 
  stl.SaveToFile('c:\aaa\'+filename);
  stl.Free;
 
  showmessage(filename+' ファイルで保存しました');
 
end;
 
end.


Mam's WebSite