In addition to the text that is written to the Description section of an event log entry, processes can also write additional byte data to the log. This data is visible in the bottom part of the event log entry, under "Data:". It can be a binary data, or it can be an additional textual data that could be helpful to you.
In the form in which it is displayed, though, it is very difficult to use effectively. As you can see in the example above, the bytes are displayed in a Window of three hard to read lines:
0000: 57 69 6e 33 32 48 52 65 Win32HRe
0008: 73 75 6c 74 3d 30 78 30 sult=0x0
0010: 30 30 30 30 30 30 30 20 0000000
You can use the scroll bar to continue reading, but you have to cut and paste the text in the far right column of the Window into another document to get the whole picture. I'll show you an app I wrote to take the guess work out of reading this information, by parsing it and writing it to a file you can open with Notepad.
The information in the Data: part of the event log entry can be broken up into three main parts. The left hand column is the byte number of the first byte of the line being displayed in the larger document. In the example above, 0000 means 0x57 is the 0th byte in the document, 0008 means 0x73 is the 8th byte in the document, and 0010 means 0x30 is the 16th byte (0010 hex == 16 in decimal) of the document.
The second part is the 8 bytes of the actual data, expressed in HEX. If the data written to the event log entry is binary then this information is only useful to some specialized reader, but if the additional data is text these bytes are the ASCII characters of the text. There are 8 bytes, delimited by spaces.
The last section of the Window is the ASCII character of the bytes. If the data is binary the characters printer will be nonsensical, but if the data is text (as it is above), the information will be displayed in 8 characters at a time. Unprintable characters, like CR, LF, TAB, and other ASCII characters lower than 32 are displayed as "." characters. It is this information I'm trying to read.
The application I wrote to assemble this information into a useful form is a console application that takes two parameters at run-time. The first parameter is the name of the file that contains the raw, unparsed event log data. The second parameter is the path to the file to create with the translated byte data.
I could have written a library to search the event log and programmatically extracted the byte data, eliminating the need to create a file of the raw data, but I didn't. I wrote it this way because the raw data is easy to get into a file, by clicking the "Copy" (two documents) button, CTRL-V the data into the Notepad and save it. Also, for my specific use, I needed to extract the data from logs exported from other machines, and there is no way to open the extracted file data with managed code. You can only programmatically open event logs that were created on the computer on which the code is running.
The code is mainly an error detection code. It ensures that:
- the right number of parameters have been passed to the executable.
- the first parameter specifies a file on disk.
- the source file can be open and read.
- once the source file is open, then there is a line that marks the start of the Data: section
Each error condition above will halt the app with a different exit code, in case you're calling this from another process, so you'll know exactly why it didn't succeed. More error checking code would be required if it wasn't for the fact that the clipboard-copied data is so rigorously formatted.
The non-error condition checking code:
- opens the file.
- chops it up into an array of
strings that define the lines.
- looks for the line that marks the start of the Data: section, since the irrelevant bits of the event log data (description, time, date, etc.) are conveniently grouped at the top of the file.
- copies the raw byte data into a new array.
- for each line of the raw byte data array, chop out the characters 6 - 30, which have the hex bytes of the data.
- chop up this sub-string into an array of
strings that define the hex bytes.
- write the ASCII character each hex byte describes to the output file.
For the event log entry pictured at the start of the article, I clicked the "Copy" button, and pasted the text into Notepad. I saved the file to c:\raw.txt, and ran the application with this command:
c:\>EventLogByteParser.exe c:\raw.txt c:\parsed.txt
This was the result put in c:\parsed.txt:
RevisionNumber=0 G=5.4.3790.2180 J=819 K=Ver 1.00PARTTBL L=2003-05-29T00:00:00
I am occasionally guilty of writing OOP apps with vast object models to accomplish fairly trivial tasks. This application was fun to write, with all the code in the
main method. I think it's a good example of the thousands of little apps a developer has to write in their career to accomplish some small, pointed task, and may shave some time from your schedule if you need to get this information in the future.
- April 10th, 2005 - Initial revision.