tags:

views:

1392

answers:

17

I know it sounds weird but I am required to put a wrapping try catch block to every method to catch all exceptions. We have thousands of methods and I need to do it in an automated way. What do you suggest?

I am planning to parse all cs files and detect methods and insert a try catch block with an application. Can you suggest me any parser that I can easily use? or anything that will help me...

every method has its unique number like 5006

public static LogEntry Authenticate(....)
        {
            LogEntry logEntry = null;
            try
            {
                ....
                return logEntry;
            }

            catch (CompanyException)
            {
                throw;
            }

            catch (Exception ex)
            {
                logEntry = new LogEntry(
                    "5006",
                    RC.GetString("5006"), EventLogEntryType.Error,
                    LogEntryCategory.Foo);

                throw new CompanyException(logEntry, ex);
            }
        }

I created this for this; http://thinkoutofthenet.com/index.php/2009/01/12/batch-code-method-manipulation/

+33  A: 

DONT DO IT. There is no good reason for pokemon ("gotta catch em all")error handling.

StingyJack
Amen to that.. scary question :)
Steven Robbins
Halfway through reading the question, all that was going through my head was "NOooooooooooooooo"
marcumka
It is not my decision guys, thanks anyway :)
erdogany
Ah, the Nuremberg Defense! (http://en.wikipedia.org/wiki/Nuremberg_Defense). This sounds like a "thin metal ruler" situation (http://blogs.msdn.com/ericlippert/archive/2003/11/03/53333.aspx) Please, please find another way to solve your problem.
Bryan Watts
@erdogany: Where did this requirement come from, and what prompted it? This may be an opportunity to exercise your ability to convince management that knee-jerk reactions to past sloppiness will only hurt because doing this will make troubleshooting problems harder, not easier.
Greg D
@greg it is decision that has been taking in the beginning of the project thousands of line has already done in this way, for me it is obvious this way is worng but, now I need to obey the rule since more than half of proj. is already in this way
erdogany
Ah, it's a monkey cage! (http://www.technochitlins.com/archives/2005/04/the_monkey_cage_1.html)
Bryan Watts
I am waiting for the "do you liek mukipz?"....
StingyJack
@erdogany: Dude, you have to beat your boss that Monkey cage link, thanks Bryan
Binary Worrier
@binary :) I am trying to convince them
erdogany
If I had a dollar every time I had to deter someone from doing this... There are highly experienced people in my team who think that this is the way to go, so I can understand the plight that erdogany is going through. Die... enemies of good design.
Bobby Alexander
+2  A: 

I'm with StingyJack, don't do it!

However if the Gods on high decree that must be done, then see my answer to this question Get a method’s contents from a cs file

Binary Worrier
+1  A: 

I had to do something kinda sorta similar (add something to a lot of lines of code); I used regex.

I would create a regex script that found the beginning of each function and insert the try catch block right after the beginning. I would then create another regex script to find the end of the function (by finding the beginning of the function right after it) and insert the try catch block at the end. This won't get you 100% of the way there, but it will hit maybe 80% which would hopefully be close enough that you could do the edge cases without too much more work.

Kevin
You can do this directly within Visual Studio: http://msdn.microsoft.com/en-us/library/2k3te2cs(VS.80).aspx
Greg
+10  A: 

Well if you have to do it, then you must. However, you might try to talk whoever is forcing you to do it into letting you use the UnhandledException event of the AppDomain class. It will give you a notification about every uncaught exception in any method before it is reported to the user. Since you can also get a stack trace from the exception object, you'll be able to tell exactly where every exception occurs. It is a much better solution than rigging your code with exception handlers everywhere. With that said, if I had to do it, I'd use some regular expressions to identify the begin and end of each method and use that to insert some exception handler everywhere. The trick to writing a regular expression for this case will be Balancing Group Definition explained more in the MSDN documentation here. There is also a relevant example of using balancing groups here.

scott
+2  A: 

First of all, I'm with StingyJack and Binary Worrier. There's a good reason exceptions aren't caught by default. If you really want to catch exceptions and die slightly nicer, you can put a try-catch block around the Application.Run() call and work from there.

When dealing with outside sources, (files, the Internet, etc), one should (usually) catch certain exceptions (bad connection, missing file, blah blah). In my book, however, an exception anywhere else means either 1) a bug, 2) flawed logic, or 3) poor data validation...

In summary, and to completely not answer your question, are you sure you want to do this?

lc
+3  A: 

Maybe whoever came up with the requirement doesn't understand that you can still catch all exceptions (at the top) without putting a try-catch in every single function. You can see an example of how to catch all unhandled exceptions here. I think this is a much better solution as you can actually do something with the exception, and report it, rather than blindly burying all exceptions, resulting in extremely hard to track down bugs.

This is similar to Scott's solution, but also adds an event handler to the Application.ThreadException exception which can happen if you are using threads. Probably best to use both in order to catch all exceptions.

Kibbee
A: 

I guess you could use Aspect Oriented programming, something I would like to my hands dirty with. For example http://www.postsharp.org/aopnet/overview

Although this sort of requirements are indeed evil.

Alex
A: 

If you really have to do it, why go to the trouble of modifying the source code, when you can modify the compiled executable/library directly

Have a look at Cecil (see website), It's a library that allows you to modify the bytecode directly, using this approach, your entire problem could be solved in a couple of hundred lines of C# code.

bmotmans
+3  A: 

See my answer here which describes some of the performance trade offs you will be forced to live with if you use "gotta catch em all" exception handling.

As scott said the best way to do pretty much the same thing is the UnhandledException event. I think jeff actually discussed this very problem in an early SO podcast.

Alex
+1  A: 

I wanted to write this as an answer to all answers then you can be aware via question RSS; requirement comes from our technical leader: here is his reason: we need no find out which func has a problem in production code, any problem has been reported as an alert, we put a unique code to ecery catch block and we see where the problem is. He knows there is a global error handling but it does not help in this scenario, and stacktrace is not accure in release mode, so he requires a try catch block like this:

everyMethod(...){
    try
    {
    ..
    catch(Exception e)
    {
       RaiseAlert(e.Message.. blabla)
    }
}
erdogany
How is the stack not accurate in release mode?!
Michael Haren
That's what I was thinking. Maybe he means you can't get the exact line, and just the actual function the error occured in, but I don't see how putting exception handlers in every function would aleviate this.
Kibbee
Michael, I tried but it is not accurate (I am talking about Exception.StackTrace), think about obfucating, optimization ... ?
erdogany
yes, just like Kibbee says you can only get the func name where you handled the exception, think if you have handled your exceptions in AppError you will get AppError func name from stacktrace anytime
erdogany
erdogany
If you're trying to debug production, maybe you could deploy it with debugging symbols, at least temporarily until you've discovered the error. Or is this more of a "just in case" thing?
Greg
@greg for me this is not a bad idea but this -raisealert- solution has longer life in decisioner's perspective
erdogany
Optimizing the code won't break the stacktrace. Obfuscation might, I suppose. At the point you're describing, implementing a GetLastError() would be less painful. I assume you've used "throw;" instead of "throw ex;" in AppError to maintain the stack trace instead of destroying it?
Greg D
yes we are using "throw;" what do you mean by GetLastError() ?
erdogany
http://msdn.microsoft.com/en-us/library/ms679360(VS.85).aspx << Something like this. Your design lead is insisting on legacy language error-handling techniques, might as well do it in the legacy style so people can tell up front what's happening. Can you convince them to read this SO thread? ;)
Greg D
I'm confused that the stack trace isn't accurate. You are looking at the InnerExceptions too when necessary, correct?
lc
A: 

Since you are posting a question here, I am sure this is one of those things you just have to do. So instead of banging your head against an unyielding wall, why not do what Scott suggested and use the AppDomain event handler. You'll meet the requirements without spending hours of quality billable hours doing grunt work. I am sure once you tell your boss how much testing updating each and every file would entail, using the event handler will be a no-brainer!

Tundey
A: 

So you are not really looking to put the same exact try-catch block in each function, right? You are going to have to tailor each try-catch to each function. Wow! Seems like a long way to "simplify" debugging.

If a user reports an error in production, why can't you just fire up Visual Studio and reproduce the steps and debug?

Tundey
Exactly what we should do, but the application is public application, thounds of people will you it on streets and no body can actually report any bug or steps
erdogany
A: 

If you absolutely have to add the try/catch block to every method and scott's answer (AppDomain.UnhandledException) is not sufficient, you can also look into interceptors. I believe the Castle project has a fairly good implementation of method interceptors.

Matthew Brubaker
+1  A: 

If you put a RaiseAlert call in every method, the error stacks you receive will be very confusing, if not inaccurate, assuming that you reuse methods. The logging method should really only need to be called in events or the top-most method(s). If someone is pushing the issue that exception handling needs to be in every method, they don't understand exception handling.

A couple years back we implemented a practice that exception handling had to be done in every event and one developer read it as "every method." When they were finished, we had weeks worth undoing to do because no exception reported was ever reproducible. I'm assuming they knew better, like you do, but never questioned the validity of their interpretation.

Implementing AppDomain.UnhandledException is a good backup but your only recourse in that method is to kill the application once you log the exception. You'd have to write a global exception handler to prevent this.

Austin Salonen
+1  A: 

so here is an example for those wondering; 5006 is unique to this method;

public static LogEntry Authenticate(....)
        {
            LogEntry logEntry = null;
            try
            {
                ....
                return logEntry;
            }

            catch (CompanyException)
            {
                throw;
            }

            catch (Exception ex)
            {
                logEntry = new LogEntry(
                    "5006",
                    RC.GetString("5006"), EventLogEntryType.Error,
                    LogEntryCategory.Foo);

                throw new CompanyException(logEntry, ex);
            }
        }
erdogany
Fyi, it's more useful if you put updates like this in the original question so that people who come to the question later can get the entire context of the question without reading the entire page. :)
Greg D
I don't understand why we're wrapping all exceptions in CompanyException, TraceListeners can help with logging at the catch point, e.g., then throw; if the exception isn't handled. Wrapping it hides the stack trace if you don't pull out the inner exception later.
Greg D
A: 

If you really have to do it, an alternative to wrapping the exception each time would be to use Exception.Data to capture the additional information and then rethrow the original exception ...

catch (Exception ex)
{
  logEntry = new LogEntry("5006",
                    RC.GetString("5006"), EventLogEntryType.Error,
                    LogEntryCategory.Foo);
  ex.Data.Add("5006",logEntry);
  throw;
}

Now at the top level you can just dump the contents of ex.Data to get all the additional information you might want. This allows you to put file names, useragents, ... and all manner of other useful information in the .Data collection to help understand why an exception occurred.

Hightechrider
A: 

I did some research work that require parsing of C# code about 2 years ago and discover that the SharpDevelop project has source code that does this really well. If you extracted the SharpDevParser project (this was two years ago, not sure if the project name stays the same) from the source code base, you can then use the parser object like this:

CSharpBinding.Parser.TParser = new CSharpBinding.Parser.TParser();
SIP.ICompilationUnitBase unitBase = sharpParser.Parse(fileName);

this gives you the compUnit.Classes which you can iterate through each class and find method within it.

Fadrian Sudaman