Archives
 
 
 
  Special
 
 
 
  About Us
 
 
 

Newsletter
Free E-mail Newsletter from BYTE.com

 
    
           
Visit the home page Browse the four-year online archive Download platform-neutral CPU/FPU benchmarks Find information for advertisers, authors, vendors, subscribers Request free information on products written about or advertised in BYTE Submit a press release, or scan recent announcements Talk with BYTE's staff and readers about products and technologies

ArticlesWindows NT Event Logging


April 1996 / Core Technologies / Windows NT Event Logging

Windows NT has a well-defined error management system

Terry Frederick

One of the most important functions of any mainframe applications software is the reporting of processing errors. Error reporting is a critical tool computer operators can use to ascertain the health of their systems.

Windows NT programmers can use an error-reporting API that categorizes errors by application, severity, category, and event. Contrast this with most OSes, where error reporting is inconsistent, virtually up to the idiosyncrasies of the programmer. NT also provides tools to analyze e rrors. Remote procedure calls (RPCs) manage these tools. Thus, networked operators can examine errors occurring on remotely located compute rs.

Additionally, NT has a set of APIs to read and manage the error logs. These APIs let the NT programmer build sophisticated error-monitoring and analysis tools that are consistent across applications. In this article, we will demonstrate the various APIs that generate error messages and describe how NT monitors events.

Quick Start

It's often worthwhile to get your code up and running as soon as possible. Here is a quick-and-dirty subroutine that will send an error to the NT error event log:


#include <windows.h>
#include <stdio.h>
void SendLogMessage (char *szMsg)
{
 HANDLE  hSource;
 char    *szList[1];
  szList[0]=szMsg;
  hSource = RegisterEventSource(NULL, "MYPROGRAM");
  if (hSource != NULL)  {
     ReportEvent(hSource,EVENTLOG_INFORMATION_TYPE,
         0,ERROR_MESSAGE,NULL,1,0,szList,NULL);
     DeregisterEventSource(hSource);  }
}
void main (argc, argv)
int     argc;
char    *argv[];
{ SendLogMessage("This is a
 generic information message");
}


RegisterEventSource is similar to an open() function; it returns a handle you can use to send messages to the event log. The parameter " MYPROGRAM " identifies which subsystem is sending the error. If " MYPROGRAM " is unknown to the event logger, the logger will default to reporting the message to the application log.

This program gets your message to the log, but it defeats the nifty features of NT's error logging. Because " MYPROGRAM " is an unknown subsystem to the event logger, you can't set up a filter to display only the " MYPROGRAM " errors. Also, the event type is always EVENTLOG_INFORMATION_TYPE , the category is always zero, and the event ID is zero (the second, third, and fourth arguments).

The first enhancement you should make is to identify your application name to the event logger. You do this by adding entries into the registry in the event log area (see the listing "How to Add Entries to the Event Log" ). Note: You must be logged on as administrator to execute this program and change the registry.

After executing this code (you will need a main() routine to call InstallSource() ), you can execute the regedt32 program, select the HKEY_LOCAL_MACHINE window, then the SYSTEM group, CurrentControlSet, Services, Eventlog, Application, and finally (whew!) MYPROGRAM to verify the entries did get created and look reasonable. The value for TypesSupported should be 7.

Meaningful Messages

Having defined your application for the event log, you can look in the event viewer and set a filter under the view menu to display only "MYPROGRAM" errors. However, there is more in this InstallSource() subroutine than merely declaring your application name.

Why did we add a value under the MYPROGRAM area called " EventMessageFile " and give it a value of " MYDLL.DLL "? We also added a value called TypesSuppo rted, containing the flags EVENTLOG_ERROR_TYPE , EVENTLOG_WARNING_TYPE , and EVENTLOG_INFORMATION_TYPE . Obviously, the TypesSupported flags represent the types of errors that can be reported within the MYPROGRAM subsystem, but what is " MYDLL.DLL " and what does it represent?

One of the banes of error logging is the inability to change error messages after the programmer has compiled the code and sent it to production to be installed. Imagine an error-reporting system that separates the error messages from the application program, so that the error messages can be changed to accommodate understandable English rather than the jargon that programmers often produce. (We especially like the message we've seen from many different programmers: "Invalid error code.") Or imagine being able to change messages to another language entirely, without changing one line of code.

The NT developers created the concept of a message DLL. Such a DLL contains "almost" no code and is s imply a shell to hold message strings. The message strings are generated outside the DLL and can be implemented in a manner similar to other resources (e.g., dialog boxes and ICONs). In other words, the resource compiler binds the messages into the DLL. The complete DLL code looks like this:


#include <windows.h>
BOOL WINAPI DllMain(HINSTANCE hDLL,
    DWORD dwReason, LPVOID lpReserved)
{ return(TRUE);
}


A message compiler included in Microsoft Visual C++ generates the resource file used to create the noncode contents of the DLL. The input source to the message compiler follows a simple format to represent the error message. It contains the error code's symbolic name, the error code, and the error text. Dynamically generated error messages are also supported.

Here's a simple example of the message file:


MessageId=1
SymbolicName=TEST_ERROR_1
Language=English
This is error event code 1.
   .
   MessageId=2
SymbolicName=TEST_ERROR_2
Language=English

This is event code 2.
   .
   MessageId=999
SymbolicName=ERROR_MESSAGE
Language=English
%1
.


The output from the message compiler is an .h file that you include in your application program. This .h file contains the symbolic names of your error message along with the associated error code. An .rc source file and a .bin file with the actual messages to be input to the DLL compiler are also generated.

If you save the preceding source in a file called mydll.mc , you can create the .h , .rc , and .bin files with the command mc mydll.mc .

To generate the MYDLL.DLL , simply create a new project in Visual C++ of type DLL, add the message DLL source and the output .rc and .bin files from the message compiler, and then build the DLL. You should then copy the generated DLL to the system DLL directory, and the .h file to your applications directory for inclusion in your a pplication. (A help file that describes all the features of the message compiler is found in the Visual C++ msdev\bin directory and is called mc.hlp .)

The listing "Event-Logging Application" is the complete source to a console application that registers itself to the event logger and then sends messages based on our sample message file.

Last Log

As NT moves into the applications server environment, NT programmers can do it right and generate consistent error reports that easily plug into error management systems. We hope we've shown that the NT event-logging system can be something useful, not something to ignore.


How to Add Entries to the Event Log



void InstallSource()
{
HKEY hk;
int disposition, allowed;
char szName[256];

strcpy(szName,"SYSTEM\\CurrentControlSet\\
Services\\
    Eventlog\\Application\\");
 strcat(szName,"MYPROGRAM");
 if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,szNam
e,
     0,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,
     NULL,&hk,&disposition))
 {  printf("Unable to create registry key");
    return;
 }
 strcpy (szName,"%SystemRoot%\\System\\MYDLL.DLL");
 if
(RegSetValueEx(hk,"EventMessageFile",0,
REG_EXPAND_SZ,
      (LPBYTE)szName,strlen(szName)+1))
 {  printf("Unable to create/set registry
      value (message DLL name)");
   return;
 }

allowed=EVENTLOG_ERROR_TYPE
EVENTLOG_WARNING_TYPE
   EVENTLOG_INFORMATION_TYPE;
 if (RegSetValueEx(hk,"TypesSupported",0,REG_DWORD,
     (LPBYTE)&allowed,sizeof(DWORD)))
 { printf("Unable to create/set registry value (message types)");
   return;
 }
 RegCloseKey(hk);
}






Event-Logging Application


#include "mydll.h"
#include <windows.h>
#include <stdio.h>
void SendLogMessage (HANDLE hSource,
  DWORD errcode, WORD errtype, char *szMsg)
{ char    *szList[1];
  if (szMsg!=NULL)
  { szList[0]=szMsg;
    ReportEvent(hSource,er
rtype,0,errcode,
     NULL,1,0,szList,NULL);
  }
  else
    ReportEvent(hSource,errtype,0,errcode,
      NULL,0,0,NULL,NULL);
}

void main (argc, argv)
int     argc;
char    *argv[];
{ HANDLE  hSource;
 InstallSource();
 hSource = RegisterEventSource(NULL,
   "MYPROGRAM");
 SendLogMessage(hSource,TEST_ERROR_1,
    EVENTLOG_WARNING_TYPE,NULL);
 SendLogMessage(hSource,TEST_ERROR_2,
    EVENTLOG_ERROR_TYPE,NULL);
 SendLogMessage(hSource,ERROR_MESSAGE,
    EVENTLOG_INFORMATION_TYPE,
    "This is a generic information message");
 DeregisterEventSource(hSource);
}


Terry Frederick is a consultant working for Sprint. He has 27 years of programming experience. You can reach him at terryf@sound.net .

Up to the Core Technologies section contentsGo to previous article: Go to next article: Marrying ISDN to the OSSearchSend a comment on this articleSubscribe to BYTE or BYTE on CD-ROM  
Flexible C++
Matthew Wilson
My approach to software engineering is far more pragmatic than it is theoretical--and no language better exemplifies this than C++.

more...

BYTE Digest

BYTE Digest editors every month analyze and evaluate the best articles from Information Week, EE Times, Dr. Dobb's Journal, Network Computing, Sys Admin, and dozens of other CMP publications—bringing you critical news and information about wireless communication, computer security, software development, embedded systems, and more!

Find out more

BYTE.com Store

BYTE CD-ROM
NOW, on one CD-ROM, you can instantly access more than 8 years of BYTE.
 
The Best of BYTE Volume 1: Programming Languages
The Best of BYTE
Volume 1: Programming Languages
In this issue of Best of BYTE, we bring together some of the leading programming language designers and implementors...

Copyright © 2005 CMP Media LLC, Privacy Policy, Your California Privacy rights, Terms of Service
Site comments: webmaster@byte.com
SDMG Web Sites: BYTE.com, C/C++ Users Journal, Dr. Dobb's Journal, MSDN Magazine, New Architect, SD Expo, SD Magazine, Sys Admin, The Perl Journal, UnixReview.com, Windows Developer Network