Backing up event logs in their normal binary format

Some time ago I was looking for a way to make backups of the eventlogs of our server, preferably without me ever having to do anything anymore J


This was not success. There are a couple of tools to make text exports from eventlogs. These have the disadvantage that they make the logs very large and unsuitable for looking at with the even viewer. As an added bonus, these are slow too (since every item has to be read individually).


EventQuery.vbs is one of these tools and it is so dog slow that it is almost a crime that it has been included with Windows. Ever wanted to bring a domain controller slow to a crawl? Simple: Use EventQuery.vbs to export the security event log. That’ll do it.


Anyway, I checked with my fellow MVPs, and there is no built-in (or free) tool to save event logs as binary event log files, so I gave up.


But then I accidentally discovered that there is a win32 API that exposes the event log functionality. And as luck would have it, I am a programmer and thus perfectly suited to make such a thing myself. It would have been trivial to make it at work, but I decided to do this at home so that I could share the code.


It is of course perfectly possible that such a free tool exists and I simply didn’t find it.


The code


The code is simple, though the line count was increased by the desire to implement error handling.


int _tmain(int argc, _TCHAR* argv[])
{
  _TCHAR* computerName = NULL;
  _TCHAR* logName = NULL;
  _TCHAR* file = NULL;

  //populate the variables, based on the input arguments
  if(argc == 3)
  {
    computerName = NULL;
    logName = argv[1];
    file = argv[2];
  }
  else if(argc == 4)
  {
    computerName = argv[1];
    logName = argv[2];
    file = argv[3];
  }
  else
  {
    Usage();
    return -1;
  }

  //Open the eventlog
  HANDLE hEventLog = OpenEventLog(computerName, logName);
  if(NULL == hEventLog)
  {
    _tprintf_s(TEXT(“Could not open eventlog %s on computer %s\n”),
      logName, computerName);
    PrintError();
    return -1;
  }

  //backup the event log to file
  if(FALSE == BackupEventLog(hEventLog, file))
  {
    _tprintf_s(TEXT(“Could not save eventlog to file %s\n”), file);
    PrintError();
    CloseEventLog(hEventLog);
    return -1;
  }

  CloseEventLog(hEventLog);
  return 0;
}


There is little to tell about the code. It can be invoked with either 2 or 3 command line arguments:


  • The name of the computer of which the logs have to be backed up. (optional)
  • The name of the event lot to back up
  • The path of the file to which the event log needs to be saved.

The application opens the event log, and then makes the backup and closes the eventlog. If something goes wrong, the error code and error message are printed to the command line.


I thought about making the error handing a little more elegant (so that PrintError and CloseEventlog were not used multiple times in the code) but with only 2 function calls, the amount of error handling code would not diminish or be any better.


I left the PrintError function out of this blog because it doesn’t do anything exciting. It retrieves the error code and prints out the corresponding error message.


What you need to know before using this tool


I’ve been using this tool for a week now, and it is working splendidly, but there are a couple of things that aren’t mentioned in the MSDN documentation of the API.


The first is that the supplied path is absolute for the computer of which you are making an even log backup. So if the path is D:\app.evt, it will make the backup to D:\app.evt on the remote computer.


The second thing you need to know is that providing a UNC name for the target file doesn’t really improve things all that much. Because what is happening under the hood is that it is not you who is making the backup.


The event log service is in charge of the event log files, and you are asking it to make a backup. And that is where it all goes pear shaped. The event log service runs with  LOCAL_SYSTEM credentials. This means that by default, it has no credentials that are valid on a remote computer. So you cannot make backup files in network locations, because the event log service of the remote computer has no privileges to access the location.


There are 2 exceptions to this rule. 1) the remote location is on the remote computer itself. 2) the remote computer is a backup domain controller.


It is a little known fact (I didn’t know it either) that LOCAL_SYSTEM on a domain controller is a domain administrative account that can pretty much do anything and everything on any domain computer, including the things that even a domain admin cannot.


Conclusion


I needed a convenient tool for making backups of event log files, and now I have one. Both the source and the binary are included as attachments. The source is available under the MIT license, and the exes are available for free to do with them what you want, as long as it is understood that whatever you do with them is your responsibility, not mine.


The eventtool_clr exe is something I made to create and delete event logs. I don’t think I blogged about it yet, but what it does is so simple it’s hardly worth mentioning. Have a look at the sources for more info.


The binary is for those who just want to use it and don’t care. The source is for those who’d rather not run an untrusted binary from some guy on the internet on their internal servers J The sources are simple enough to audit and compile.


On a side note, The API to backup event logs is not exposed on the .NET api for event logs. I don’t know exactly why, but I suspect that it is because of the problems I mentioned. The API is confusing enough that it is really not fit for generic use. After all, you can’t backup to remote systems, and the path is absolute for the remote computer.


I also didn’t want a .NET program, because for this type of thing, nothing beats the convenience and performance of a compiled binary that needs no runtime DLLs or external frameworks.


 

Don’t people read anymore before commenting?

Blogs are funny things. We all have different reasons to write blog posts. Apart form the general stuff that almost everybody sometimes writes about (opinion pieces, general comments about something or other) I like writing tech articles.


Programming is my hobby, and sometimes I like to set myself a challenge, or want to see what sort of interesting things I can do with a given API / language / platform. Afterwards, I write an article about what I did, partially because I actually like writing things like that, and partially because you don’t know if you understand something fully until you can sucessfully explain it to someone else, leaving out no details.


You’d be amazed about how many things you take for granted until you are forced to explain them step by step. And you’ll quickly find out that some things you’ve never thought about twice were wrong.


Anyway,  It takes a lot of time to write a detailed article about something technical (much longer than you’d expect). And I always hope that if you care enough about it to comment on it, you’ve actually read it. But sadly, I am often disappointed.


Take this article for example. I wrote it as an example of how it is possible to create a fifo queue without locks. In the article I mention that there is 1 writer, and 1 reader, and that my implementation is thread safe, specifically because of that. And after all, this is a simplified proof of concept of something, so lack of advanced features (like signalling) is to be expected.


And yet a lot of people comment the same thing every time ‘Your code is wrong, this bit has a race condition. this is a basic mistake’ and variations thereof. And then I think to myself ‘Yes, of course there is a bloody race condition. That is why I mention that there should be only 1 reader and 1 writer!’ What makes it even worse is that a number of people already commented this, and that I’ve already answered that comment several times.


I am definitely not a prima donna programmer. I never mind explaining something about my code or design, even if I have to do it a couple of times. And I really welcome comments, bugreports and other feedback about my code. If I made a mistake, I’d like to know. But I hate it when people start spewing comments without even bothering to read the article and / or the comments that have already been posted. Is it really that hard not to make an idiot of yourself?

Using reflection to ease code maintenance

Currently I am programming an application for performing code analysis on the software that controls the production process. Apart from the parsing of the code, and iterating across a hierarchical representation of the expression tree, all these rules (verifications) have to be executed against all the code.


I could change the code verifier every time I implemented a new rule, but instead I used reflection to do this for me. Every verification that has to be done is represented by a class that implements the right interface. This interface defines the prototype of the method that performs the verification.


  interface IActionVerification
  {
    void Verify(CodeContext context);
  }


The context variable contains the complete context of the portion of the code that is being looked at: the current action, step, function block and phase.


When a new code verifier instance is create, it will use reflection to examine the current assembly, and extract all classes that implement this interface.


  public CodeVerifier()
  {
    actionVerifications = new List<IActionVerification>();
    var currAssembly = Assembly.GetExecutingAssembly();
    foreach(Type t in currAssembly.GetTypes())
    {
      if (null != t.GetInterface(typeof(IActionVerification).Name))
        actionVerifications.Add(
          (IActionVerification)
             currAssembly.CreateInstance(t.FullName));
    }
  }


This way, it is very easy to populate the list of all verifications to do. The code verification itself is conceptually as simple as this:


  foreach (var verification in actionVerifications)
    verification.Verify(context);


Implementing a new verification is the as easy as creating a new class and implementing the interface. After that everything will be done automatically. Ading a new verification is as easy as this:


  class ActionExpressionCount : IActionVerification
  {
    public void Verify(CodeContext context)
    {
      if (context.Action.ParsedExpression.Count < 1)
        ActionExpressionCountInvalid.LogIssue(context);
    }
  }


Hip hip hooray for the .NET framework!