NT Event Logging


To use the event logging function under Windows NT, you need to setup a number of things first. Windows NT uses the registry to locate files (.EXE or .DLL) that contain resource strings. Adding resources to your application requires some Microsoft SDK tools. (mc.exe, rc.exe, cvtres.exe)

From your application you can use RegisterEventSource and ReportEvent functions to actually log messages to the event log service. The name specified as a parameter to RegisterEventSource must match the name of the key in the registry (here ):

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application\[servicename]

This key holds the following values:

(REG_EXPAND_SZ) EventMessageFile  value: [application filename]
(REG_DWORD)     TypesSupported    value: 7

Note: The [application filename] must contain the complete path + file specification.

The next thing to do is to write a file to hold the predefined message strings:

;// -- log_event.mc ------------------------------------------------------------
;// 
;// This file contains predefined messages
;//
;// ----------------------------------------------------------------------------
;
MessageIdTypedef=DWORD
;
;
;///////////////////////////////////////////////////////////////////////////////
;//
;// Information Messages
;//
;///////////////////////////////////////////////////////////////////////////////
;
MessageId=0
Severity=Informational
Facility=Application
;SymbolicName=INF_xxxx
Language=English
Hello world (%1!s!).
.
;

compile this file using the message compiler MC.EXE and also generate a header file to show the event-id's that you need to pass with the ReportEvent function.

mc -o log_event.mc
Now you have a log_event.rc resource file that you need to compile to get a linkable object file.

rc -r -dWin32 -fo log_event.tmp log_event.rc
Convert the object file using cvtres.exe and delete the temporary file

cvtres -i386 log_event.tmp -o log_event.rbj
del log_event.tmp
The resulting .RBJ file can be linked with your application. Here's an example application that logs an event.


   with System;
   with Text_IO;
   with Win32;
   with Win32.Winbase;  use Win32.Winbase;
   with Win32.Winnt;    use Win32.Winnt;

   use type System.Address;
   use type Win32.DWORD;

   procedure Log_Event is

   pragma Linker_Options ("log_event.rbj");

      type LPSTR_Array is array (natural range <>) of aliased Win32.LPCSTR;
      WindowsNT    : Boolean;
      hEventSource : Win32.Winnt.HANDLE;
      lpszStrings  : aliased LPSTR_Array (1 .. 1);  -- Parameter(s) to the message
      fResult      : Win32.BOOL;
      dwEvent_Id   : Win32.DWORD := Win32.DWORD (16#40000000#);
      wType        : Win32.WORD  := Win32.Winnt.EVENTLOG_INFORMATION_TYPE;

      Service_Name : String := "Log_Event";
      Message      : String := "Event";

   begin
      WindowsNT := (Win32.Winbase.GetVersion < 16#80000000#);

      if not WindowsNT then
         Text_IO.Put_Line ("Eventlogging only supported on Windows NT");
      else

         declare
               --internal name of the service
            RegServiceName  : constant String := Service_Name & ascii.nul;
            CMessage        : constant String := Message & ascii.nul;
         begin
               -- Use event logging to log the error.

            hEventSource := Win32.Winbase.RegisterEventSource
                               (NULL,                         -- On local machine (otherwise supply 
                                                              -- UNC name of the NT server)
                                Win32.Addr (RegServiceName)); -- Name of source (in registry)

            lpszStrings(1) := Win32.Addr (CMessage);
            --lpszStrings(2) := Win32.Addr (...);

            if hEventSource /= System.null_address then
               fResult := Win32.Winbase.ReportEvent
                             (hEventSource,             -- handle of event source
                              wType,                    -- event type
                              0,                        -- event category
                              dwEvent_Id,               -- event ID
                              System.null_address,      -- current user's SID
                              lpszStrings'Length,       -- strings in lpszStrings
                              0,                        -- no bytes of raw data
                              lpszStrings(1)'access,    -- array of error strings
                              System.null_address);     -- no raw data

               fResult := Win32.Winbase.DeregisterEventSource(hEventSource);

            else
               Text_IO.Put_Line ("Unable to register the eventsource");
            end if;
         end;
      end if;

   end Log_Event;

Next compile and link this program. In this case I used GNAT 3.11. Other compilers may have a different way to link resources to the executable.

gnatmake log_event
Now use the Regedit32 registry editor and create the key:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application\Log_Event

values:
(REG_EXPAND_SZ) EventMessageFile  value: c:\...\Log_Event.exe
(REG_DWORD)     TypesSupported    value: 7
The application is now ready to run. Afterwards you can use the event logger application to see the result.
Contributed by: Rob Veenker
Contributed on: April 6, 1999
License: Public Domain
Back