When developing and running web applications, such as web sites or web services, it is nice and convenient to have some logging from the application. Instead of using a log file it would be nice to be able to use the built-in event log in Windows.

When running or debugging a web application from Visual Studio using the built-in web server, named WebDev.WebServer.EXE when looking in the task manager, it will cause no trouble logging to the event log but when publishing the site or service to a server environment, Windows 2003 Server and IIS, it will cause the application to crash. The IIS log file will show an error, status 500, indicating an internal server error. The application will crash due to insufficient permissions for the application to write to the event log.

Don’t worry! There are a couple of solutions to this and I will present one of them here, with the ability to be treated as a little tool for those who develop .NET web applications.

The Solution

Background

Actually I found the base for the solution below on the CodeProject site where Subbiah Anandan wrote about it in his article about Centralized Event Logging in .NET Using Web Services.

I tried to make his solution more general, to fit when ever you need to use it for your web applications. See the ToDo section for improvements to be done.

This is the way

First of all the basic event logging is based on an application, a source, writing a short information text, error and debug information, using the mechanisms built-into the operating system. The source for locally installed services or applications doesn’t need to be known when doing the logging, if the log used is registered on the system.

This is not the case when loggning from web applications, because of security issues. The web applications are in most cases run as a non-administrator user, preventing them from messing up the server environment.

Therefor we need to install or register the source for the web application to use when using the event log. In .NET Framework 2.0 there is a utility called InstallUtil, to be used when registering stuff in the Windows registry. The InstallUtil is able to use the installer information in a .NET assembly. In this case we don’t need to produce an .EXE file, so let’s start off by creating a Class Library project, producing a .DLL file, in Visual Studio instead. The Visual Studio solution already contains a web service project, added when the solution was created.

Right click the solution, then Add -> New Project…

The project is added to the solution in Visual Studio.

Remove the Class1.cs file from the project, and add a new class named TheEventLogInstaller and let it inherit the Installer class contained in the System.Configuration.Install namespace. You have to add a reference to System.Configuration.Install if the namespace is not found.

After the new class is added you have to enable it to be used by the InstallUtil tool by adding [RunInstaller(true)] before the class:

This is the foundation for this little tool we’re developing here.

Note that the icon in front of the code file may be changed by Visual Studio, to look like a service icon.

Let the class contain a property of type EventLogInstaller. You can make this private. This object will be added to the InstallerCollection in the constructor for the class.

To make the installer DLL useful it would be nice to be able to pass parameters to it, by using command line parameters. Something like this would be nice:

InstallUtil.exe /logsourcename=MyWebService WebServiceEventLogInstaller.dll

To accomplish this we can override the Install and Uninstall methods in the Installer class. In these two methods we have access to the assembly context of the class and therefor to the parameters passed to the InstallUtil tool, like the parameter logsourcename above.

In the Install and Unistall methods, call a private method to validate the parameters for this class, maybe exit the install or uninstall process if the parameters are not correct. You will also be able to add text to the log file created by the InstallUtil tool.

The value of the parameters can be used for setting properties on the EventLogInstaller object added to the class above.

The complete source code for this little class will then look something like this:

    [RunInstaller(true)]
    public class TheEventLogInstaller : Installer
    {
        private EventLogInstaller theEventLogInstaller;

        private string logSourceName;
        private string log;

        private void CheckAndInitiate()
        {
            logSourceName = this.Context.Parameters["logsourcename"];
            log = this.Context.Parameters["log"];

            if (logSourceName == null)
                throw new Exception("Parameter [logsourcename] missing");

            theEventLogInstaller.Source = logSourceName;

            if (log == null)
            {
                this.Context.LogMessage("Parameter [log] missing, using 'Application'.");
                log = "Application";
            }

            theEventLogInstaller.Log = log;
        }

        public override void Uninstall(System.Collections.IDictionary savedState)
        {
            CheckAndInitiate();
            base.Uninstall(savedState);
        }

        public override void Install(System.Collections.IDictionary stateSaver)
        {
            CheckAndInitiate();
            base.Install(stateSaver);
        }

        public TheEventLogInstaller()
        {
            theEventLogInstaller = new EventLogInstaller();
            Installers.Add(theEventLogInstaller);
        }
    }

As you can see I use the Context.LogMessage on line 21 to add a warning text to the InstallUtil log file if the user of this tool doesn’t provide the parameter log.

On line 28 and 34 are the overridden Uninstall and Install methods, containing the method call to CheckAndInitiate to read the parameters passed to the InstallUtil tool.

Note that the uninstall procedure have to be exactly like the install procedure, but you pass an extra parameter, /u, to the InstallUtil tool like this:

InstallUtil.exe /u /logsourcename=MyWebService WebServiceEventLogInstaller.dll

This somewhat feature is needed because the base.Install and base.Uninstall doesn’t know which event log source to use.

Usage

The solution above is very handy to use if there’s a need for a web application to use the event log. Add the class library project to the solution for the web application, reference the class library project from the web site or web service and the installer .DLL will be copied to the /bin folder when publishing the web application. The logsourcename parameter passed to the InstallUtil can be defined in the web.config file and used in the web application when logging things.

The steps below will demonstrate the usage:

1. Add a reference to the class library project

Right click on the web service project and Add Reference…

2. Add an appSettings key-value node

The web.config file is located in the root of the web service project. It will be placed in the root of the published one as well.

3. Publish the web service

Right click on the web service project and Publish…

4. Run InstallUtil with the same parameters as in web.config

The .DLL file is located in the /bin folder of the published web service.

InstallUtil.exe /logsourcename=MyWebService WebServiceEventLogInstaller.dll

5. You’re ready to try your web service out

Verify that the event log gets new log records. In the event log there will be entries, caused by consuming the following web method:

If everything goes well, your web application will happily use the event log as you like and Windows will allow it to do so.

ToDo

Here are some improvements to be done in the future:

  • Make the installation use the Windows registry to identify the source used. This will make the uninstall procedure easier, because the logsourcename parameter will not be needed as far as the uninstallation is performed in the same place as the installation.
    This may be accomplished by storing the abolute path of the /bin folder of the web application and the logsourcename parameter value to the registry.
  • The log parameter passed to the install procedure is used, but the actual Log in the event log may not exist and therefor the install procedure will fail or install the source in the Application log. The installer will have to create the Log if it doesn’t exist.
    Note: This feature makes the logging from the web application a little bit more complicated. I will post examples when the feature is added.

These extra features, and maybe more, will be added and I will write about it here as soon as it is done.

Read more

Please read the article referenced above: Centralized Event Logging in .NET Using Web Services.

For information about the Windows event log, consult the MSDN Library about the System.Diagnostics Namespace.

Note

The source code in this article is “as-is” and I do not want be held responsible for any damage to the Windows registry when using it.
Be careful when creating applications that modifies the Windows registry!

Feel free to use this and modify it as you like, but don’t blame me for bad things…

  2 Responses to “Windows event log and web applications”

  1. This topic is quite hot in the net right now. What do you pay the most attention to while choosing what to write ?

  2. I want to buy a house, but I have no money.

 Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

   
© 2011 freddes.se Suffusion theme by Sayontan Sinha