Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2011-09

Read Windows EventLog...

2 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Ludo Brands
to Liyuan García Caballero
Show quoted text 9 lines
Hello team Somebody know how read from Windows EventLog with Free Pascal and Lazarus? Liyuan

A quick and dirty program:

program dumpEventLog;
uses windows,sysutils,classes;
procedure geteventlog(const provider: string; var sl:TStringList) ;
var hnd:HANDLE;
  lpBuffer: Pointer;
  pnBytesRead, pnMinNumberOfBytesNeeded: DWORD;
  pRecord: PEVENTLOGRECORD;
  eventtype,sdate,computer,source,data:string;
  user,domain:array [0..255] of char;
  userlen,domlen:dword;
  datestart:TDateTime;
  peUse: SID_NAME_USE;
  p:pchar;
  i:integer;
begin
  hnd:=OpenEventLog(nil,pchar(provider));
  if hnd0 then
    begin
    datestart:=EncodeDate(1970,1,1);
    getmem(lpbuffer,$10000);
    while ReadEventLog(hnd,EVENTLOG_SEQUENTIAL_READ or
EVENTLOG_BACKWARDS_READ, 0,
      lpBuffer, $10000, pnBytesRead, pnMinNumberOfBytesNeeded) do
      begin
      pRecord:=lpBuffer;
      while pRecord< lpBuffer+pnBytesRead do
        begin
        case pRecord^.EventType of
           EVENTLOG_ERROR_TYPE       :eventtype:='Error';
           EVENTLOG_WARNING_TYPE     :eventtype:='Warning';
           EVENTLOG_INFORMATION_TYPE :eventtype:='Information';
           EVENTLOG_AUDIT_SUCCESS    :eventtype:='Audit Success';
           EVENTLOG_AUDIT_FAILURE    :eventtype:='Audit Failure';
           end;
        sdate:=DateTimeToStr(datestart+pRecord^.TimeGenerated/24/3600);
        if pRecord^.UserSidLength=0 then
          begin
          user:='N/A';
          domain:='N/A';
          end
        else
          begin
          userlen:=256;
          domlen:=256;
LookUpAccountSID(Nil,PSID(pointer(pRecord)+pRecord^.UserSidOffset),user,user
len,domain,domlen,peUse);
          end;
        source:=pchar(PSID(pointer(pRecord)+sizeof(TEventLogRecord)));
computer:=pchar(PSID(pointer(pRecord)+sizeof(TEventLogRecord)+length(source)
+1));
        data:='';
        p:=pchar(pointer(pRecord)+pRecord^.StringOffset);
        for i:=1 to pRecord^.NumStrings do
          begin
          data:=data+p+';';
          p:=p+strlen(p)+1;
          end;
        sl.Add(format('Number: %d  Date: %s ID: %d  Type: %s Category: %d
User: %s Domain: %s Computer: %s Source %s Data: %s',
           [pRecord^.RecordNumber,sdate,pRecord^.EventID and $FFFF ,
eventtype ,pRecord^.EventCategory ,
           user,domain,computer,source,data]));
        pRecord:=PEVENTLOGRECORD(pointer(pRecord)+pRecord^.Length);
        end;
      end;
    freemem(lpbuffer);
    CloseEventLog(hnd);
    end;
end;
var
  sl:TStringList;
  i:integer;
begin
  sl:=TStringList.create;
  geteventlog('Security',sl);
  for i:=0 to sl.Count-1 do
    writeln(sl[I]);
  sl.destroy;
end.

Change Security to Application to System or ... to get the other logs.

This program just dumps the data strings unformated. To get the nice error message as displayed in the event viewer, quite some more work is needed. The data in the eventlog are just the variable parts in a formatted string. To get the format string you need to take the source of the event (say crypt32 in the Application log), read the registry value HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\cr ypt32\EventMessageFile which is the filename of a dll, load that library, lookup the resource with ID EventID and substitute the data in the format string.

Ludo

Reply by email