# seaEvent.pl script searches for matching eventlog entries on [remote] machine. # # written 14-may-04 by fgb # # NB: raw eventID must be processed to correspond with what you see in eventviewer # by ANDing with value 0xffff (see code) - I don't know why but it works. # require "ctime.pl"; use Win32::EventLog; $bDebug = 0; my $sAppName = "seaEvent"; my $nCount = 0; my $nDbgRecLimit = 10; my $nFirst = 0; my $bHelp = 0; my $sId = ""; my $bIsLocal = 1; my $evtLog; my $sLocalMachine = Win32::NodeName; my $sMachine = ""; my $nMatches = 0; my $sMsg = ""; my $sNow = &ctime(time); my $bQuiet = 0; my $sSrc = ""; my $sType = "application"; my $bVerbose = 0; my $sVersion = "1.0"; _main: parseCmdArgs(); if ($bHelp) { help(); exit; } if ($bVerbose) { print "$sAppName $sVersion startup at $sNow"; } if ($#ARGV+1) { $sMachine = shift @ARGV; $bIsLocal = 0; } if ($bIsLocal) { $sMachine = $sLocalMachine; } if ($nDebug) { print "dbg: machine=$sMachine; islocal=$bIsLocal\n"; } print "\nSearching $sMachine"; if ($sId ne "") { print " (id=$sId)"; } if ($sSrc ne "") { print " (src=$sSrc)"; } print ":\n"; ### Search eventlog for matching entries: $evtLog = Win32::EventLog->new($sType,$sMachine) || die "can't open eventlog (r u admin?): $!\n"; unless ($evtLog->GetOldest(\$nFirst)) { errMsg("can't retrieve oldest recno"); goto _bye; } unless ($evtLog->GetNumber(\$nCount)) { errMsg("can't retrieve eventlog count"); goto _bye; } my $n = $nFirst + $nCount; if ($bDebug) { print "dbg: oldest=$nFirst total=$nCount\n"; $nDbgRecLimit = $n + 10; } ++$n; while ($evtLog->Read((EVENTLOG_FORWARDS_READ | EVENTLOG_SEEK_READ),$n,$entry)) { $bMatchesId = $bMatchesSrc = 0; ++$n; if (! $bQuiet) { if ($n % 3) { print '.'; } } # feedback script is running if ($bDebug) { print "#$n> src: " . $entry->{Source} . " id: " . ($entry->{EventID} & 0xffff); print " time: " . scalar localtime($entry->{TimeGenerated}) . "\n"; if ($n == $nDbgRecLimit) { last; } } if ($sId ne "") { $nID = ($entry->{EventID} & 0xffff); if ($sId ne "" && $nID ne $sId) { if ($bDebug) { print "dbg: $nID ne $sId\n"; } next; } else { $bMatchesId = 1; } } if ($sSrc ne "") { if ($entry->{Source} !~ /$sSrc/i) { next; } else { $bMatchesSrc = 1; } } $nID = ($entry->{EventID} & 0xffff); Win32::EventLog::GetMessageText($entry); $sMsg = $entry->{Message}; $sTimeStmp = scalar localtime($entry->{TimeGenerated}); print "\n$entry->{Source} $nID $sTimeStmp $sMsg"; if ($bMatchesId || $bMatchesSrc) { ++$nMatches; } } $evtLog->Close(); print "\n$nMatches entries found"; if ($bVerbose) { print " out of $n searched." } print "\n"; _bye: if ($bVerbose) { print "\n$sAppName complete.\n"; } ### subroutines: sub errMsg($) { my $s = "$sAppName error: " . @_[0]; print "$s\n"; if ($bVerbose) { errorReport(); } } sub errorReport { print Win32::FormatMessage(Win32::GetLastError()); } sub help { print "$sAppName $sVersion - search eventlog for matching source and/or id entries\n"; print "written 19-may-2004 by Frank Brown\n"; print "\nusage: $sAppName /type={app|sys} [/id=n] [/source=string] [/quiet] [\\\\machine]\n"; print "\nexample: $sAppName /typ=sys /id=22 \\\\somePC /qui \>\\reports\\somePCsus.lis\n"; print "\nThe example above searches the system eventlog for entries matching ID=22 on\n"; print "machine \\\\somePC. /qui suppresses printing '.'s during the search.\n"; print "Output is redirected to file \\reports\\somePCsus.lis\n"; } sub parseCmdArgs { my $s = ""; while (@ARGV) { $_ = shift @ARGV; if ($bDebug) { print "dbg: parsing $_\n"; } if (/^[\/\-]/) { # is arg a switch? $arg = lc(substr($_,1,3)); # parse 1st 3 chars: if (($arg eq 'hel') || (substr($arg,0,1) eq '?')) { &help(); exit; } elsif ($arg eq "deb") { $bDebug = 1; } elsif ($arg eq "ver") { $bVerbose = 1; } elsif ($arg eq "qui") { $bQuiet = 1; } elsif ($arg eq "typ") { $i = index($_,"="); $i++; $s = lc(substr($_,$i,3)); if ($s eq 'app') { $sType = 'application'; } if ($s eq 'sys') { $sType = 'system'; } if ($bDebug) { print "dbg: type=$sType\n"; } } elsif (substr($arg,0,2) eq "id") { $i = index($_,"="); $i++; $sId = sprintf("%s",substr($_,$i)); if ($bDebug) { print "dbg: ID=$sId\n"; } } elsif ($arg eq "sou") { $i = index($_,"="); $i++; $sSrc = sprintf("%s",substr($_,$i)); if ($bDebug) { print "dbg: source=$sSrc\n"; } } } else { if ($bDebug) { print "$_ not a switch\n"; } # not a switch if (/^\\\\.*/) { # machine name (UNC) s/\s(.*)//; # remove whitespace s/^\\\\//; # remove leading \\ $sMachine = $_; $bIsLocal = 0; } } } } __END__