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

Mamの覚書Q&A検索

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


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

「 プリンターのイベントログを読む 」

プリンターのイベントログを読む


回答

ソース

unit Unit1;
 
interface
 
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs,IPHLPAPI, Vcl.StdCtrls, Vcl.Grids,
  Vcl.ExtCtrls
  ,registry;
 
type
  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    Panel1: TPanel;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure get_event_log(SourceName:String;stl:TStringList);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;
 

  // 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;       //Reserved
    ClosingRecordNumber : DWORD;//Reserved
    StringOffset : DWORD;
    UserSidLength : DWORD;
    UserSidOffset : DWORD;
    DataLength : DWORD;
    DataOffset : DWORD;
    // Then follows Variant Area .....
    // TWCHAR SourceName[]
    // TWCHAR Computername[]
    // SID   UserSid
    // TWCHAR Strings[]
    // BYTE  Data[]
    // CHAR  Pad[]
    // DWORD Length;
  end;
 
  TEventLogRecord =EVENTLOGRECORD;
 
var
  Form1: TForm1;
 
const
  EVENTLOG_SEQUENTIAL_READ    = 1;
  EVENTLOG_SEEK_READ          = 2;
  EVENTLOG_FORWARDS_READ      = 4;
  EVENTLOG_BACKWARDS_READ     = 8;
 

function TimeGeneratedToDateTime(aTimeGenerated: DWORD): TDateTime;
 
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.Button1Click(Sender: TObject);
var
  stl:TStringList;
  stl2:TStringList;
  i,c:integer;
  r:Integer;
  reg:TRegistry;
  ret:boolean;
begin
 
  reg:=TRegistry.Create;
  reg.RootKey:=HKEY_LOCAL_MACHINE;
  ret:=reg.CreateKey('\SYSTEM\CurrentControlSet\Services\EventLog\Microsoft-Windows-PrintService/Operational');
  reg.Free;
  //if ret then showmessage('レジストリ作成成功');
  //exit;
 
  //HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog
    //Application
    //HardwareEvents
    //Internet Explorer
    //Key Management Service
    //Media Center
    //Security
    //System
    //Windows PowerShell
 
  Screen.Cursor:=crHourGlass;
  StringGrid1.Visible:=False;;
 
  stl:=TStringList.Create;
  stl2:=TStringList.Create;
  stl.Clear;
  stl2.Clear;
  stl2.QuoteChar:='"';
  stl2.StrictDelimiter:=true;
  stl2.Delimiter:=',';
 
  StringGrid1.ColCount:=30;
  StringGrid1.Rows[0].CommaText:='日時,イベントID,ソース名,コンピューター名,イベントタイプ,ユーザー名,ドメイン'
           +',セキュリティID,アカウント名,アカウントドメイン,ログオンID,オブジェクトサーバー,オブジェクト種類,オブジェクト名'
           +',ハンドルID,トランザクションID,アクセス,アクセスマスク,特権,制限されたSID数,プロセスID,プロセス名';
  r:=1;
 
  //4624 ログオン
  //4634 ログオフ
 
  //4656 ファイルオープン           (オブジェクトサーバーがSecurity、オブジェクト種別がFile)
  //4656 その他オブジェクトアクセス (オブジェクトサーバーがPlugPlayManager、オブジェクト種別がSecurity)
 
  //4658 ファイルクロース
  //4663 ファイルアクセス
  //4690 ファイルコピー
  //4660 ファイル削除
 
  //4672 特殊なログオフ
 

{
  get_event_log('Application',stl);
  for i := 0 to stl.Count-1 do
  begin
    StringGrid1.RowCount:=r+1;
    stl2.CommaText:=stl[i];
    for c := 0 to stl2.count-1 do
    begin
      StringGrid1.Cells[c,r]:=stl2[c];
    end;
    inc(r);
  end;
 
  stl.Clear;
  get_event_log('HardwareEvents',stl);
  for i := 0 to stl.Count-1 do
  begin
    StringGrid1.RowCount:=r+1;
    stl2.CommaText:=stl[i];
    for c := 0 to stl2.count-1 do
    begin
      StringGrid1.Cells[c,r]:=stl2[c];
    end;
    inc(r);
  end;
 
  stl.Clear;
  get_event_log('Internet Explorer',stl);
  for i := 0 to stl.Count-1 do
  begin
    StringGrid1.RowCount:=r+1;
    stl2.CommaText:=stl[i];
    for c := 0 to stl2.count-1 do
    begin
      StringGrid1.Cells[c,r]:=stl2[c];
    end;
    inc(r);
  end;
 
  stl.Clear;
  get_event_log('Key Management Service',stl);
  for i := 0 to stl.Count-1 do
  begin
    StringGrid1.RowCount:=r+1;
    stl2.CommaText:=stl[i];
    for c := 0 to stl2.count-1 do
    begin
      StringGrid1.Cells[c,r]:=stl2[c];
    end;
    inc(r);
  end;
 
  stl.Clear;
  get_event_log('Media Center',stl);
  for i := 0 to stl.Count-1 do
  begin
    StringGrid1.RowCount:=r+1;
    stl2.CommaText:=stl[i];
    for c := 0 to stl2.count-1 do
    begin
      StringGrid1.Cells[c,r]:=stl2[c];
    end;
    inc(r);
  end;
}
 
//WinVist、7以降でUACが有効の場合、昇格しないと表示されない
  stl.Clear;
 
  //get_event_log('Security',stl);
  //get_event_log('Microsoft-Windows-PrintService%4Operational',stl);
  //get_event_log('Microsoft-Windows-PrintService\Operational',stl);
 
  //get_event_log('Microsoft-Windows-PrintService Operational',stl);
 
  //get_event_log('C:\Windows\System32\winevt\Logs\Microsoft-Windows-PrintService\/Operational.evtx',stl);
  //get_event_log('Security',stl);
 
  get_event_log('Microsoft-Windows-PrintService/Operational',stl);
  //get_event_log('Windows PowerShell',stl);
 
  for i := 0 to stl.Count-1 do
  begin
    StringGrid1.RowCount:=r+1;
    stl2.CommaText:=stl[i];
    for c := 0 to stl2.count-1 do
    begin
      StringGrid1.Cells[c,r]:=stl2[c];
    end;
    inc(r);
  end;
 
{
  stl.Clear;
  get_event_log('System',stl);
  for i := 0 to stl.Count-1 do
  begin
    StringGrid1.RowCount:=r+1;
    stl2.CommaText:=stl[i];
    for c := 0 to stl2.count-1 do
    begin
      StringGrid1.Cells[c,r]:=stl2[c];
    end;
    inc(r);
  end;
 
  stl.Clear;
  get_event_log('Windows PowerShell',stl);
  for i := 0 to stl.Count-1 do
  begin
    StringGrid1.RowCount:=r+1;
    stl2.CommaText:=stl[i];
    for c := 0 to stl2.count-1 do
    begin
      StringGrid1.Cells[c,r]:=stl2[c];
    end;
    inc(r);
  end;
}
 

  if r>1 then
  begin
    StringGrid1.FixedRows:=1;
    StringGrid1.ColWidths[0]:=100;
    StringGrid1.ColWidths[1]:=64;
    StringGrid1.ColWidths[2]:=128;
    StringGrid1.ColWidths[3]:=64;
    StringGrid1.ColWidths[4]:=200;
    StringGrid1.ColWidths[5]:=100;
    StringGrid1.ColWidths[6]:=100;
    StringGrid1.ColWidths[7]:=256;
 
  end;
 
  stl2.Free;
  stl.Free;
 
  StringGrid1.Visible:=True;
  Screen.Cursor:=crDefault;
 

end;
 
procedure TForm1.get_event_log(SourceName: String;stl:TStringList);
const
  //最新のログから順次読み込む
  READ_FLAG= EVENTLOG_SEQUENTIAL_READ or EVENTLOG_BACKWARDS_READ;
var
  eLogHandle: THandle;
  logCount: DWORD;
  i,j: Integer;
  eventID: Integer;
  pBuf: PEventLogRecord;
  bufSize: Integer;
  readNum, readNeed: DWORD;
 

  off:Cardinal;
  dwAccountSize, dwDomainSize: DWORD;
  szAccount, szDomain: array[0..MAX_PATH] of Char;
 

  ust:String;
  dst:String;
  us:PSID;
  peUse: Cardinal;
 
  st,strn:string;
  p:PChar;
 
  gSourceName:string;//
  gComputername:string;//
  gTimeGenerated:TDateTime;
  gEventType:Word;
  gEventTypeSt:string;
  gString:string;
  b:TBytes;
 
  stl2:TStringList;
 
begin
  //HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog
    //Application
    //HardwareEvents
    //Internet Explorer
    //Key Management Service
    //Media Center
    //Security
    //System
    //Windows PowerShell
    //Domain Mapper  ????分からないのもがある
 
  stl2:=TStringList.Create;
 
  //システムログのオープン
  eLogHandle := OpenEventLog(nil,PWideChar(SourceName));
  //eLogHandle := OpenEventLogA(nil,PAnsiChar(SourceName));
 
  //クリア
  //lastLogOn := 0;
  //lastLogOut := 0;
 
  //Memo1.Lines.Clear;
 
  //ログが開けた場合に
  if eLogHandle > 0 then
  begin
    //ログ数を取得
    if not GetNumberOfEventLogRecords(eLogHandle, logCount) then
      logCount := 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;
 
      //イベントIDを読む
      eventID := pBuf^.EventID AND $FFFF;
      //イベントタイプ
      gEventType:=pBuf^.EventType;
      case gEventType of
        $1:gEventTypeSt:='EVENTLOG_ERROR_TYPE';
        $2:gEventTypeSt:='EVENTLOG_WARNING_TYPE';
        $4:gEventTypeSt:='EVENTLOG_INFORMATION_TYPE';
        $8:gEventTypeSt:='EVENTLOG_AUDIT_SUCCESS';
        $10:gEventTypeSt:='EVENTLOG_AUDIT_FAILURE';
        else gEventTypeSt:='EVENTLOG_UnKnown';
      end;
 
      //ドメイン、ユーザー名を取得
      ust:='';
      dst:='';
      off:=pBuf^.UserSidOffset;
      us:=@(PAnsiChar(pBuf)[off]);
      if (pBuf^.UserSidLength>0) then
      begin
        dwAccountSize:= MAX_PATH;
        dwDomainSize:= MAX_PATH;
        if (not LookupAccountSid(nil, us, szAccount, dwAccountSize,
                                 szDomain, dwDomainSize, peUse)) then
        begin end
        else
        begin
          ust:=(szAccount);
          dst:=(szDomain);
        end;
      end;
 
      //発生日時を取得
      gTimeGenerated := TimeGeneratedToDateTime(pBuf^.TimeGenerated);
 
      //ソース名を読み取る
      p:=PChar(DWORD(pBuf)+Sizeof(TEventLogRecord));
      gSourceName:=StrPas(p);
 
      //コンピューター名を読み取る
      p:=PChar(DWORD(pBuf)+Sizeof(TEventLogRecord)+length(gSourceName)*2+2);
      gComputername:=StrPas(p);
 

      stl2.Clear;
      //文字列を読み取る
      gString:='';
      st:='';
      off:=pBuf^.StringOffset;
      if pBuf^.NumStrings>0 then
      begin
        if pBuf^.NumStrings>1 then
        begin
          if pBuf^.EventID=302 then
            st:=st;
        end;
        for j := 0 to pBuf^.NumStrings-1 do
        begin
          p:=PChar(DWORD(pBuf)+off);
          st:=StrPas(p);
 
          strn:=st;
          strn:=StringReplace(strn,',',' ',[rfReplaceAll]);
          strn:=StringReplace(strn,#10,' ',[rfReplaceAll]);
          stl2.Add(strn);
          gString:=gString+strn;
 
          inc(off,length(st)*2+2);
        end;
      end;
 

 
      //バイナリデータを読み取る
      setlength(b,pBuf^.DataLength);
      for j := 0 to pBuf^.DataLength-1 do
      begin
        b[j]:=PByte(DWORD(pBuf)+pBuf^.DataOffset+j)^;
      end;
 
      {
      st:='';
      for j := pBuf^.StringOffset to pBuf^.DataOffset-1 do
      begin
        st:=st+Char(PChar(DWORD(pBuf)+j));
      end;
      }
 
      //   4656 ファイルオープン    4663 ファイルアクセス    4690 ファイルコピー
      //   4660 ファイル削除        4658 ファイルクローズ
 
      //if stl2.Count>5 then
 
      //if (pBuf^.EventID=4656) or (pBuf^.EventID=4663) or (pBuf^.EventID=4690) or (pBuf^.EventID=4660) or (pBuf^.EventID=4658) then
      //if stl2[5]='File' then
      if (pBuf^.EventID=307) or (pBuf^.EventID=310) then  //307は印刷完了を示す。310は削除されたことを示す
      begin
        stl.Add(
          FormatDateTime('yyyy/mm/dd hh:nn:ss', gTimeGenerated)+','+
          inttostr(eventID)+','+gSourceName+','+gComputername+','+
          inttostr(gEventType)+'<'+gEventTypeSt+'>'+','+
          ust+','+dst+','+stl2.CommaText
        );
      end;
    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;
 
  stl2.Free;
 
end;
 
end.


Mam's WebSite