Here's how Report.pl works. The script first creates a hash with the event-log entry values. The script then creates an instance of the Win32::EventLog object and passes the hash to the Report() method, which creates the log entry.
If a message table uses multiple strings (e.g., string1, string 2), you need to pass in multiple strings when reporting an event. However, the Report() method doesn't support multiple strings in version 0.062 of Win32::EventLog. Although version 0.071 fixes this problem, you must use the null character ("\0") to separate multiple strings. A better solution is to use the WriteEventLog() function instead of the Report() method. The script Report2.pl uses the WriteEventLog() function to perform the same tasks as Report.pl. So, if you need to submit multiple strings, use Report2.pl rather than Report.pl.
You can use the reporting scripts Report.pl and Report2.pl many ways. You can call one of the reporting scripts from another script to write any errors that the calling script might encounter in an event log. You can even call a reporting script from a script to write a log entry that indicates that the calling script successfully executed. In addition, you can use a reporting script to log an event. Suppose you just replaced a SCSI drive; you can call Report.pl to make a note of this replacement in the event log when the SCSI drive boots up.
Report.pl and Report2.pl are intentionally simplistic so that you can easily see how to submit event-log entries. You can adapt these scripts to interact with other scripts and services to provide more hearty event-logging capabilities.
Monitoring Event Logs with WMI
Windows Management Instrumentation (WMI) is a cool new technology that you ought to become familiar with. WMI lets scripts connect to local and remote machines and query them for information about their event logs, services, hardware, and other mechanisms and processes. WMI comes with Win2K and Windows Millennium Edition (Windows Me) and is available for other Windows platforms. You can download the core WMI components for NT 4.0 and Windows 9x from http://msdn.microsoft.com/downloads/c-frame.htm?/downloads/sdks/wmi/default.asp.
Like the Win32::EventLog extension, WMI lets scripts display the entries in a machine's event log. Unlike the Win32::EventLog extension, WMI lets scripts monitor changes in an event log. Thus, an incredibly useful aspect of WMI is that it lets a script monitor new event-log entries; the script EventMon.pl performs this task. This script connects to a remote machine and displays the new event-log entries.
Listing 2 contains an excerpt from EventMon.pl. The code at callout A in Listing 2 highlights an exciting part of WMI: the moniker string. The moniker string "winmgmts:{impersonationLevel=impersonate,(security)}//$Machine/" procures the WMI COM object. In this string, winmgmts: tells Win32 that you want to access the WMI service on the machine that $Machine specifies. In this case, $Machine specifies a remote machine. If you want to access the local machine's WMI service, you place a period (".") in the $Machine variable. The {impersonationLevel=impersonate,(security)} portion of the string instructs Win32 to connect to the remote machine by using the credentials of the user running the script.
The code after callout A in Listing 2 tells the WMI service to query all event-log entries submitted to the remote machine. The code uses the SQL query "select * from __instancecreationevent where targetinstance isa 'Win32_NTLogEvent'". This query looks for all (*) instances of a newly created event (__instancecreationevent) that is a Win32 event log (isa 'Win32_NTLogEvent').
If all goes well, the WMI service queues the new log events until the script fetches them with the code
my $Event =
$Events->NextEvent( $TIMEOUT );
This code uses the WMI COM object's NextEvent() method to retrieve the new log events. The value that you pass to this method ($TIMEOUT) specifies how many milliseconds you want to wait for an event. If the time passes without the NextEvent() method retrieving any event, the method generates an error. The error's HRESULT value is 0x80043001, which signifies a timeout condition. If the NextEvent() method is successful, it returns a WMI Win32_NTLogEvent object. The script then uses this object to print out the various properties of that log event entry.
To run EventMon.pl, you type
perl eventmon.pl server
at the command line, where server is the name of the remote machine you want to access.
Just for fun, run EventMon.pl and let it continue to display new events. Then, open another DOS window and run Report.pl to submit an event-log entry. After the new event-log entry has been submitted, you'll see the entry displayed in the output of EventMon.pl.
Not So Hard After All
As I've demonstrated, event logs are not too difficult to query and adapt. You just need to know how the event log works and how to use such tools as the Win32::EventLog extension, the WriteEventLog() function, and WMI. With a bit of experimentation, these tasks will become quite easy and manageable.