5

I am new to software development and also new to stackoverflow, so go easy on me.

BACKGROUND: I am developing a C# class library that processes xml messages sent by a third party application over tcp/ip (using Async sockets). I am using com-interop in order to expose the class library to a Vb6 application. When the C# library processes the xml it receives over the socket, it raises various events that the consuming vb6 application subscribes to (this way, when we eventually rewrite the entire application in .Net we will already be done with this component).

QUESTION: I want to catch all unhandled exceptions for LOGGING PURPOSES ONLY. In a winforms application you can hook up an event to the AppDomain.CurrentDomain.UnhandledException and to Application.ThreadException. Is there no way to similarly grab exception data to log the information in a class library?

Important Points:

  • I am not trying to recover from these exceptions, but just log them and let the exception propogate up and crash the app if need be.

  • I am doing my best to catch all specific exceptions locally wherever I know that they might occur. Therefore my purpose is to just log the truly unexpected exceptions.

  • I know that some will say that this would be a bad design pattern. I should instead let the caller deal with these exceptions. The problem is the vb6 application does not have as robust error handling in place as I would like. Primarily, I want to log the stack trace so that if the vb6 app crashes due to my dll, I can view the log in order to be alerted to potential areas of my c# code that might need to be changed.

Can anyone provide me with some direction? The best option that I have found so far seems to put a generic try catch block in every public method, log the exception, and then throw it. This seems less than ideal:

public void SomeMethod()
{
    try
    {
        // try something here...
    }
    catch (Exception ex)
    {
        Log(ex);
        throw;
    }
}

Not only does this seem like a poor design, but additionally I do not know what would happen if one of the async callbacks causes an exception on a different thread than the method was called on. Would this general try/catch block still catch such an exception?

Thanks for any assistance.

EDIT: I originally marked @Eric J.'s answer as correct, but after trying to implement the solution I have found that it won't work well with the async callbacks from the socket class that I am using. Once a threadpool thread is used to fire the async callback, I cannot seem to catch any exceptions that occur any later in the stack. Will I need to use an AOP framework, or is there any other way to catch these exceptions?

Joe DePung
  • 991
  • 3
  • 11
  • 21
  • The real issue here was that I did not have a top-level catch block in my async callback functions. Since they are run on separate threads (thread-pool threads), their exceptions don't 'bubble' back up anywhere else. AOP seems like a good solution for this scenario to avoid so many top-level catch blocks. It is something I intend to invest a little time in a little further down the road. – Joe DePung Nov 17 '11 at 22:01
  • Why is AppDomain.CurrentDomain.UnhandledException not working for class library? – Felix Keil Oct 17 '19 at 05:31

3 Answers3

2

If you have a limited set of entry points to the library, consider doing just what you suggest - use a .NET wrapper class or wrapper library to perform the actual interop and catch/log the exception in that wrapper class. Return an exception or error code that the calling VB6 library knows how to handle (whether that's rethrowing the exception or not depends on what the VB6 code can deal with).

CrazyDart suggests IOC, which is an interesting and valid alternative but also adds complexity and learning curve initially. Certainly have a look at IOC as well and concider it as a possibility.

Eric J.
  • 147,927
  • 63
  • 340
  • 553
  • It doesn't seem like the ideal solution from a paradigmatic standpoint, but again, given my time constrains looks like the best option for the present project. Thanks for the input. Just for clarification, are you suggesting an extra layer of wrapping, or just what is required to do the com interop? – Joe DePung Jul 29 '11 at 14:43
  • No, just a single layer that does the COM interop and handles exceptions. If you have a large number of methods to wrap, you would consider writing a little code generator that e.g. takes a list of methods per class in COM and outputs the appropriate C# code. I did that before when wrapping a very large COM business layer. Then again if it's really large, it may be worth investing time in IOC. – Eric J. Jul 29 '11 at 18:33
  • Thanks. Marking as answer because this solution works best for me at this time. – Joe DePung Jul 30 '11 at 15:04
  • Unfortunately, I tried to implement this but I am running into issues with exceptions thrown after an async callback is called. See my edit above. Please advise if you can think of a way to catch these exceptions. – Joe DePung Aug 01 '11 at 19:19
  • Well, with the lack of other responses... I'll mark this as the final answer. I will note, however, that the main thing I needed in this situation was to make sure that I used a top-level catch statement at the beginning of every thread, including Async callback functions. – Joe DePung Nov 17 '11 at 21:58
1

You could use Castle Windsor and an interceptor for this. Its a good reason to use IOC on projects.

http://blog.andreloker.de/post/2009/02/20/Simple-AOP-integrating-interceptors-into-Windsor.aspx

I have used them for exception logging, just as you stated, and performance logging... among many other things you use interceptors for like transactions.

CrazyDart
  • 3,803
  • 2
  • 23
  • 29
  • I have used IOC on projects and personally believe that it adds the most benefit on large projects with several teams responsible for different areas (different concerns). I know that's treading into holy war territory, just sharing my personal experience. – Eric J. Jul 27 '11 at 19:35
  • Everything has its place... the question is on an advanced subject IMHO and requires a rather advanced approach to solve correctly. I agree with some of the other posts that AOP (just about the same as interceptors) is a valid approach. Philosophically, some choose to never plant a fruit tree. I plant many often. Later I have great harvests. Many people ask me how I came to have so many great looking fruit trees and I tell them I plant often. Some die, and many dont. To neglect learning because it is hard is what makes someone suitable for service and labor jobs rather than engineering. – CrazyDart Jul 28 '11 at 21:37
  • Thanks CrazyDart. I agree that the problem seems rather advanced, and may require an advanced approach. Unfortunately all of this is new to me (I've been developing only for about 6 mos, full-time for only the last 2 months). I've bookmarked both the AOP frameworks and Castle Windsor for the future. Given my time constraints on the present project I am leaning towards Eric's approach. If you have any specific insights or concerns about this in the above scenario, feel free to advise. Thanks again. – Joe DePung Jul 29 '11 at 14:11
  • Knowing your experience level, I would say dont try to bite off IOC yet. It is rather advanced and you will end up with many headaches. Wait a few years on IOC. – CrazyDart Jul 29 '11 at 15:55
  • @CrazyDart: I agree... continuous learning is key to mastering the art and profession. – Eric J. Jul 29 '11 at 18:34
1

You could either look at using an AOP framework like Spring.NET or Unity, or alternatively look at a product such as PostSharp (though I have never personally tried PostSharp).

lowds
  • 1,085
  • 8
  • 12
  • Thanks for the info. I will bookmark these frameworks and come back to them in the future. For now, I am afraid the learning curve may be too great to implement given my time constraints on the project. – Joe DePung Jul 29 '11 at 14:04