Listing 1: EventMonitor.pl use vars qw( $Log $Message %Config ); use strict; use Getopt::Long; use Win32::OLE qw( HRESULT ); # BEGIN CALLOUT A my $TIMEOUT = -1; my %HRESULT = ( success => HRESULT( 0x00000000 ), timeout => HRESULT( 0x80043001 ), ); my %EVENT_TYPE = ( error => 1, warning => 2, information => 3, audit_success => 4, audit_failure => 5, ); %Config = ( types => [] ); Configure( \%Config ); if( $Config{help} ) { Syntax(); exit; } my $SqlQuery = "select * from __instancecreationevent where targetinstance isa 'Win32_NTLogEvent'"; if( scalar @{$Config{types}} ) { my @WhereClause; foreach my $Type ( @{$Config{types}} ) { if( "all" eq lc $Type ) { @WhereClause = (); last; } push( @WhereClause, " targetinstance.EventType = $EVENT_TYPE{lc $Type} " ); } $SqlQuery .= " AND ( " . join( " OR ", @WhereClause ) . " )" if( scalar @WhereClause ); } # END CALLOUT A # BEGIN CALLOUT B my $WMIServices = Win32::OLE->GetObject( "winmgmts:{impersonationLevel=impersonate,(security)}//$Config{machine}/" ) || die; my $Events = $WMIServices->ExecNotificationQuery( $SqlQuery ); if( $HRESULT{success} != scalar Win32::OLE->LastError() ) { die "Error: " . Win32::OLE->LastError() . "\n"; } # END CALLOUT B print "Listening for Win32 EventLog events on machine: $Config{machine}\n"; $~ = "EVENT_RECORD_HEADER"; write; $~ = "EVENT_RECORD"; # BEGIN CALLOUT C while (1) { my $Event = $Events->NextEvent( $TIMEOUT ); last if $HRESULT{timeout} == scalar Win32::OLE->LastError(); local( $Log ) = $Event->{TargetInstance}; local( $Message ) = $Log->{Message} || join( "\n", @{$Log->{InsertionStrings}} ); write; print "\n"; } # END CALLOUT C # BEGIN CALLOUT D sub FormatDate { my( $DateTime ) = @_; my($year, $month, $day, $hour, $min, $sec) = $DateTime =~ /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/; my $HalfIndicator = $hour >= 12 ? 'PM' : 'AM'; $hour = 12 if $hour == 0; $hour -= 12 if $hour > 12; return( sprintf( "%04d.%02d.%02d %02d:%02d:%02d %s", $year, $month, $day, $hour, $min, $sec, $HalfIndicator ) ); } # END CALLOUT D format EVENT_RECORD_HEADER = Machine Type Source Event Message --------- ------------ ------------------ -------------------------------- . format EVENT_RECORD = @<<<<<<<< @<<<<<<<<<<< @<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $Log->{ComputerName}, $Log->{Type}, $Log->{SourceName}, $Message @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< FormatDate($Log->{TimeGenerated}) $Message ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $Message ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $Message ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $Message ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $Message ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $Message . sub Configure { my( $Config ) = @_; my $Result; Getopt::Long::Configure( "prefix_pattern=(-|\/)" ); $Result = GetOptions( $Config, qw( types|t=s@ help|? ) ); $Config->{machine} = shift @ARGV || Win32::NodeName(); $Config->{help} = 1 if( ! $Result ); } sub Syntax { my ($Name) = ($0 =~ /([^\\\/]*)$/); print<