Friday, February 11, 2005

Fun with Microsoft's Enterprise Library

Oh yeah, back to my day-job: I'm a programmer.

So we've got a new application to update the current stone-tablet process in the University that determines if students actually graduate.

Now, I like to write good code, and furthermore, if someone else writes it for me, that's even better. So if you are working on the .NET platform, you'd do well to look at the Enterprise Library.

Of course, this is several thousand lines of code to pore over, good stuff, but unfortunately we have these minor annoying things called deadlines which prevents us from taking the time to grok everything properly.

Come to think of it, this happens in Physics, too -- I never have enough time to actually understand all the details of the problems I'm supposed to be solving, but my advisor assures me that this is the proper state of things in research, as opposed to writing text books, and three guesses as to which one gets you tenure.

Back to the matter at hand -- the Enterprise Library. Looking around at some good working examples , hilarity and pandemonium ensues when you try to do something simple like write to the Event Log when your application barfs. (Did I mention this doesn't come up a lot because instrumenting software seems to be a ... novelty?) I'm pretty sure that developers should not be doing things like editing the Registry, installing Services, or setting accounts programs run under with full admin rights -- I was a system administrator in a previous job, and I hated letting programmers do those kind of things.

So I won't inflict the same damage on our own, long-suffering sysadmin.

Now, my 52-line class solution doesn't do all the bells and whistles the EL does, but it sure doesn't require all the nastiness above:

using System;

using System.Diagnostics;

 

namespace CAESDO

{

    /// <summary>

    /// Methods to handle error reporting

    /// </summary>

    public class ErrorHandler

    {

        public ErrorHandler()

        {

            // Register application as source for Application log

            if (!EventLog.SourceExists("FacultyStudentSurveys"))

                EventLog.CreateEventSource("FacultyStudentSurveys", "Application");

        }

 

        /// <summary>

        /// Writes an error message to the Application Event Log

        /// </summary>

        /// <param name="error">The thrown exception</param>

        internal void WriteToEventLog(Exception error)

        {

            const string source = "Commencement";

            const string logName = "Application";

            EventLogEntryType enumType = EventLogEntryType.Error;

 

            EventLog objectLog = new EventLog(logName);

            objectLog.Source = source;

            objectLog.WriteEntry(error.Message, enumType, 1 );

        }

 

        internal void WriteToEventLog(string message, bool success)

        {

            const string source = "Commencement";

            const string logName = "Application";

            EventLogEntryType enumType;

 

            if (success)

            {

                enumType = EventLogEntryType.Information;

            }

            else

            {

                enumType = EventLogEntryType.Error;

            }

            EventLog objectLog = new EventLog(logName);

            objectLog.Source = source;

            objectLog.WriteEntry(message, enumType);

        }

    }

}



I'm sure I've missed something obvious. Anyone?

I just got a reply from the Hisam Baz, author of the above weblog which says, "Why write 52 lines of code when you can write 1?".

To which I reply, "I'd be happy to write 1 line of code -- if it works."

Which brings us to the second problem:

Non-portable references to the Global Assembly Cache in ASP.NET

Once you actually try to use the Enterprise Library, you'll often come across this bit of advice:

"References

Then from your application, add references to Microsoft.Practices.EnterpriseLibrary.Configuration.dll
and Microsoft.Practices.EnterpriseLibrary.Logging.dll from the C:\Program Files\Microsoft Enterprise Library\bin\ directory. You should consider signing the assemblies and then adding them to the GAC. You should also add a copy of the assemblies to C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE. Once you do that, you can select the assemblies directly from the "Add Reference" dialog. One you've added the reference, then add the appropriate using statement - using Microsoft.Practices.EnterpriseLibrary.Logging - to your code."

There's only one problem -- it doesn't work.

1. When Visual Studio 2003 .NET looks for references in the Global Assembly Cache, it never updates its view of the GAC in response to what you've added -- that's done by the registry (bleah). Which is why you've got to add a copy where VS can find it.

2. When writing ASP.NET applications, references should be against assemblies in the webserver GAC. And naturally, installer projects written in VS 2003 do not install the files in the GAC automatically, as they do for the web application itself. So now you have to manually add assemblies to the GAC and write registry entries for each assembly to be resolved by the .NET runtime.

Wait, why are we using the GAC again?

Okay, looks like I'll have to wade through Richard Grime's Fusion Workshop. Except that it doesn't cover the case I'm interested in. Joy.

Well, I sure hope that the 10 lines of code I'll end up emitting in this exercise will exceed the several thousand I could be writing if I just wrote everything myself.

What's that again about the virtues of programmers? Laziness, impatience, and hubris. Oh, alright then.

3 comments:

Anonymous said...

where and when are you running that error class in your app?

Anonymous said...

Again, where are you running this code, this class?

Adam Getchell said...

Well, this class is pretty old now, and Enterprise Library v3 is much better. I don't have any programs that use it any more, but it used to be invoked out of global.asax.cs.