Section 6.1. Monitoring the Event Log


6.1. Monitoring the Event Log

The operating system provides the event log service as a mechanism for allowing the system and applications running on it to record their activity in a nonintrusive fashion. If each operating system component and application decided to pop up a message whenever anything happened, an interactive user would never have a chance to get anything done. While the Event Viewer tool (eventvwr.exe) continues to allow an administrator to review, sort, and filter events from a graphical interface, MSH also provides a cmdlet for querying the event logs from within the shell.

Windows operating systems primarily store event records in three logs, separating events based on their relevance to different aspects of the system.


Application log

The application log is the place in which applications running on the system can record events of note. It's up to the application developer to determine which events are recorded in this log.


Security log

The security log records activity related to user and system authorization and authentication: failed login attempts, file creation, deletion, and modification are captured here.


System log

Operating system components use the system log to record their activity. If a driver fails to initialize some hardware, a service fails to start, or the machine itself reboots, an entry will be placed in this log.

The event log framework is extensible, meaning that installed applications and optional operating system components (such as the DNS Service) can create their own logs into which they record their events. In fact, MSH creates a MonadLog event log used for storing startup, shutdown, and other critical events related to the shell.

Let's look at some alternative ways of accessing event log records through MSH.

6.1.1. How Do I Do That?

First, let's introduce the get-eventlog cmdlet, which exposes the event log data to the shell:

     MSH D:\MshScripts> get-eventlog -list       Max(K) Retain OverflowAction        Entries Name       ------ ------ --------------        ------- ----       15,232     0 OverwriteAsNeeded           231 Application       15,360    0 OverwriteAsNeeded           305 MonadLog       30,016     0 OverwriteAsNeeded         5,407 Security       15,168     0 OverwriteAsNeeded           371 System

On a typical system, we see these four logs and some information about their size and what happens when the log reaches capacity (its overwrite behavior). Let's focus on the security log for a moment. get-eventlog can be called with the -newest option, which can be used to limit the number of records to return. Because event logs can potentially contain many thousands of entries, it's convenient and efficient to limit the number of records returned:

     MSH D:\MshScripts> get-eventlog Security -newest 10     Index Time          Type Source            EventID Message     ----- ----          ---- ------            ------- -------      5407 Aug 22 23:05  Succ Security              520 The system time was c...      5406 Aug 22 23:05  Succ Security              520 The system time was c...      5405 Aug 22 23:05  Succ Security              520 The system time was c...      5404 Aug 22 23:05  Succ Security              520 The system time was c...      5403 Aug 22 23:05  Succ Security              520 The system time was c...      5402 Aug 22 23:05  Succ Security              520 The system time was c...      5401 Aug 22 23:05  Succ Security              520 The system time was c...      5400 Aug 22 23:05  Succ Security              520 The system time was c...      5399 Aug 22 23:05  Succ Security              520 The system time was c...      5398 Aug 22 23:05  Succ Security              520 The system time was c...

Of course, the list of events here is actually a sequence of objects that have been placed into the pipeline. The familiar where-object and format-table cmdlets work well on pipeline objects, so we can start filtering and tabulating results right away. In this example, we'll look for only those events that represent a successful login and tabulate the time and username associated with the event:

     MSH D:\MshScripts> get-eventlog Security -newest 1000 | where-object     { $_.EventID -eq 528 } | format-table TimeGenerated,Username     TimeGenerated                           UserName     -------------                           --------     8/22/2005 8:42:47 PM                    MONAD\andy     8/22/2005 8:22:08 PM                    MONAD\andy     8/22/2005 6:42:07 PM                    MONAD\andy     8/22/2005 5:59:25 PM                    MONAD\andy     8/22/2005 4:50:20 PM                    MONAD\andy     8/22/2005 1:42:30 PM                    MONAD\andy     ...

There is no reason to filter only by event IDs. Let's say we're just focused on looking at system errors: we might instead choose to filter just those records with their EntryType property set to the Error. Other values that could be used include FailureAudit, Information, SuccessAudit, and Warning. Note that even though we tell get-eventlog to return 1,000 records at most, we might see significantly fewer because, of those 1,000, many may be informational or warning events:

     MSH D:\MshScripts> get-eventlog System -newest 1000 |     where-object { $_.EntryType -eq "Error"}     Index Time          Type Source           EventID Message     ----- ----          ---- ------           ------- -------       520 Aug 24 20:05  Erro DCOM                 10016 The application-speci...       518 Aug 24 20:05  Erro W32Time           39452701 The time provider Ntp...       515 Aug 24 20:05  Erro NETLOGON              5719 This computer was not...       508 Aug 24 20:05  Erro EventLog              6008 The previous system s...       505 Aug 23 09:05  Erro Tcpip                 4199 The system detected a...       502 Aug 23 09:05  Erro Tcpip                 4199 The system detected a...       501 Aug 23 08:05  Erro Tcpip                 4199 The system detected a...     ...

Because the event log is time-based, we'll often prefer to filter events on the same date range or a sliding window. The where-object cmdlet can be used to filter just those event log entries within a given range by performing tests on the TimeGenerated property:

     MSH D:\MshScripts> get-eventlog System | where-object { ($_.TimeGenerated          -gt "2005-8-22") -and ($_.TimeGenerated -lt "2005-8-23") }       Index Time          Type Source                EventID Message     ----- ----          ---- ------                ------- -------       369 Aug 22 20:05  Warn DnsApi                  11197 The system failed to                                                            ...       368 Aug 22 20:05  Info Service Control M...     7036 The WinHTTP Web                                                            Proxy...       367 Aug 22 20:05  Info WinHttpAutoProxySvc     12517 The WinHTTP Web                                                            Proxy...       364 Aug 22 20:05  Info Service Control M...     7035 The WinHTTP Web                                                            Proxy...       363 Aug 22 19:05  Warn DnsApi                  11197 The system failed to                                                            ...       362 Aug 22 18:05  Warn DnsApi                  11197 The system failed to                                                            ...       361 Aug 22 17:05  Erro NETLOGON                 5719 This computer was                                                            not...       360 Aug 22 17:05  Warn DnsApi                  11197 The system failed to                                                            ...       359 Aug 22 16:05  Warn DnsApi                  11197 The system failed to                                                            ...       358 Aug 22 15:05  Warn DnsApi                  11197 The system failed to                                                            ...     ...

It's also possible to use a dynamic date range by using the methods of the DateTime class. Let's say we want to look at the last 24 hours: we can use the AddHours method to get the exact date and time of 24 hours ago and use that in the where-object test:

     MSH D:\MshScripts> get-eventlog System | where-object     { $_.TimeGenerated -gt (get-date).AddHours(-24) }     Index Time          Type Source                EventID Message     ----- ----          ---- ------                ------- -------       538 Aug 24 20:05  Warn W32Time              39452686 The time provider                                                            Ntp...       537 Aug 24 20:05  Info Service Control M...     7036 The Windows                                                            Installer...       536 Aug 24 20:05  Info Windows Update Agent       22 Restart Required: To                                                            ...       535 Aug 24 20:05  Info Windows Update Agent       19 Installation                                                            Successf...       534 Aug 24 20:05  Info NtServicePack          921881 Windows Server 2003                                                            H...       533 Aug 24 20:05  Info Windows Update Agent       19 Installation                                                            Successf...       532 Aug 24 20:05  Info Service Control M...     7035 The SMS Process                                                            Event...       531 Aug 24 20:05  Info Windows Update Agent       18 Installation Ready:                                                            T...     ...

6.1.2. What Just Happened?

All of the read access to the event log is provided through a single cmdlet. Depending on its command-line options, it can be used to list available logs or to reveal their contents. As we've seen before, the get-member cmdlet can be used to discover the available fields of the EventLogEntry objects that get-eventlog generates. We looked at some of the interesting fields for sorting and filteringEventID, EventType, and TimeGeneratedbut others, including Source, Message, Category, and Index, also contain valuable information.

Filtering by date ranges can be especially useful when writing scripts that call out to external programs that might write their diagnostic information to the event log. By recording the time at the start of a script, it's possible to then report on any new event log entries that were created during the run. Example 6-1 shows a pseudoscript that could be used to save events to a file.

Example 6-1. List events generated during a script run
 $startTime = (get-date) # do some work # call out to external tools get-eventlog Application | where-object { $_.TimeGenerated -gt $startTime } | format-list | out-file ScriptGeneratedEventLog.txt

6.1.3. What About...

... Using this cmdlet for monitoring system health? Certainly. A script built around get-eventlog could be run periodically as a Scheduled Task. When run, it could look at all events logged since the last run and take action if any indicated a problem. While this approach works well for small systems, it may not be as easy to manage in larger deployments where tools such as Microsoft Operations Manager are better suited to the task.

The .NET Framework holds a range of methods that allow even more interaction with the event log system. Calling into the System.Diagnostics.EventLog class, it's simple to create a new event record and add it to the Application log:

     MSH D:\MshScripts> [System.Diagnostics.EventLog]::WriteEntry     ("ProcessFiles.msh", "Completed successfully")

Furthermore, an administrator can create and remove new event logs by using other methods within the same class. For example, we can use the following to create and remove a new event log called PrivateLog. After creation, this new event log will appear in the output of get-eventlog -list, as well as in the graphical eventvwr.exe tool. This could be useful as part of a deployment script for a large application in which specialized logging is required; in typical script and administration, it's more common to log notices to the Application log:

     # create a new empty log called PrivateLog     MSH D:\MshScripts> [System.Diagnostics.EventLog]::CreateEventSource("ProcessFiles.msh", "PrivateLog")     # delete log and all entries     MSH D:\MshScripts> [System.Diagnostics.EventLog]::Delete("PrivateLog")

6.1.4. Where Can I Learn More?

Help for the get-eventlog cmdlet has a review of the functionality we've covered here, with additional details on other command-line options. The MSDN documentation for the EventLog class contains details about some of the more advanced tasks: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemDiagnosticsEventLogClassTopic.asp. Also, the event ID lookup tool (http://www.eventid.net) is a useful resource when working with event logs.

Now, let's focus our attention on another part of the system plumbing: NT services.

If you've tried to use sc.exe from within MSH, you may have noticed that the experience isn't quite what you'd expect. Instead of communicating with the Service Controller, you may be presented with an obscure prompt complaining about missing parameters.

On startup, MSH creates an alias sc that points to set-content. This alias actually masks the underlying tool (since MSH always tries to run any aliases first), so typing SC from a prompt won't run the underlying program. To work around this behavior, use both the tool name and extension:SC.EXE.





Monad Jumpstart
Monad Jumpstart
ISBN: N/A
EAN: N/A
Year: 2005
Pages: 117

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net