Writing to the EventLog from a Web Application
When I was a young lad in college, I wrote undetectable viral hacks, keyboard sniffers, and collected more passwords than I care to count. (Thankfully, the statute of limitations—this was 20 years ago—has run out.) I never stole anything or wrecked anyone's data, but I did encourage a young fellow to send roses to his girlfriend and hooked a football player, Napolean XXXXXXX (last name omitted), up on a blind date. I understand the allure of going and being places one isn't allowed, but this crap makes life a pain in the butt for the rest of us.
I wonder whether you should hate hackers and those nitwits who tweak Trojans, so the rest of us have to keep sending money to McAfee?! I also wonder if maybe the sparring and jousting among programmers, Microsoft and hackers, and cyber thieves aren't necessary to push the technology forward, at least as far as security is concerned, so we all are protected from worse—cyber terrorists. With the economy in the shape it's in, an effective cyber terror attack could push the economy into the trash compactor and send normally sane people running for the bunker. The unfortunate net effect in my little community is like taking off my shoes at airport security—I have to re-learn how to do little things over.
Writing to the EventLog
If you wanted to write to the EventLog, you can still create an instance of the EventLog and call WriteEntry. By default, your entry will be written to the Application log. If you wanted to create a new log source—a dictionary entry for your application—you could write code like that shown in Listing 1.
Listing 1: Code that tries to create an event source but is doomed to fail due to a lack of permissions to the Security log.
Imports System.Diagnostics Partial Class _Default Inherits System.Web.UI.Page Protected Sub Page_Load(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Me.Load If (Not EventLog.SourceExists("MyApp")) Then EventLog.CreateEventSource(("MyApp", "Application") End If 'Write entry here EventLog.WriteEntry(SOURCE, "Test") End Sub End Class
The code checks to see whether the source exists; if not, it creates it. The EventLog uses queuing (it might be DCOM, I don't remember and it's not important right now), but there can be a latency between doing things to the EventLog and those tasks actually completing. In short, this means that it is better to create an event source in advance of needing it.
The problem with the preceding code is that it won't work. If you try to create or use a custom log, you are going to get a security exception (see Figure 1)—for sure under Windows Vista, Visual Studio 2008, and IIS 7 (and Cassini). I am not sure how many other back-combinations will cause this error; the point is that it's going to be a challenge going forward. Worse, having searched the Web thoroughly, Google returns blogs and articles that instruct one to hack the Registry security permissions for EventLogs (bad idea and not a sustainable approach) or write a look that edits the Registry with code (also clumsy). The best approach is none of these.
Figure 1: A SecurityException if you invoke SourceExists, CreateEventSource, of WriteEntry and a particular EventLog source doesn't exist.
To lead you to the solution—at least how I got there—think about these things:
- You don't want any old application updating the Registry; if some generally bad person or just a dipstick can modify your Registry, you are in for potentially disastrous problems.
- Trying to create a Registry log source will cause a security exception.
- Hacking the Registry yourself is a good way to muck up a server without outside forces or evil super-villain intercession.
- The EventLog has a built-in latency—due to DCOM queuing; well, I am pretty sure it's DCOM—so you want to establish custom event logs and sources in advance.
What do these things tell you? That's right. You need an installer for Registry changes. An installer is run by a separate application, InstallUtil.exe, that has the proper security permissions; InstallUtil needs to be run using Administrative privileges and isn't deployed in your web application. So, besides being more work and frustrating for you and me, this approach will work and will frustrate the nefarious intentions of evil-doers—at least as far as the EventLog is concerned.
Creating an Installer
The idea behind installers is that these chunks of code are separate from your deployed applications. As separate code, an installer can be run with administrative privileges (which your deployed applications probably won't be) and then taken out of the deployment environment. The benefit is that you get your application configured but reduce the risk of having code that can do things such as change the Registry in your deployment environment.
An installer is basically a DLL that contains a class that inherits from System.Configuration.Install.Installer, has the RunInstaller(True) attribute decorating the class, and some code that performs some kind of configuration. In this case, the "some code" is code that creates the event source needed for the web application demo (shown in Listing 1). To create the installer, create a separate class project file, add a reference to the System.Configuration.Install.dll to the project, and add the code in Listing 2.
Page 1 of 3