Parsing C #, finding methods and setting try / catch for all methods

I know this sounds weird, but I have to put a capture attempt for each 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 try catch block with application. Can you suggest me any parser that I can easily use? or anything to help me ...

each method has its own unique number, for example 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/

+1


source to share


18 replies


I needed to do something like similar (add something to many lines of code); I have used regex.



I would create a regex script that finds the start of each function and insert a try catch block right after the start. Then I create another regex script to find the end of the function (by finding the start of the function just after it) and insert a try try block at the end. This will not give you 100% of the path, but it will reach perhaps 80%, which will hopefully be close enough for you to do edge cases effortlessly.

+1


source


Do not do this. There is no good reason to handle pokemon errors ("gotta catch em all").



EDIT: A small revision happened a few years later. Instead, I would say, "At least don't do it manually." Use an AOP tool or a loom like PostSharp or Fody to apply this to the final result code, but be sure to consider other useful trace or diagnostic data points like capture times, inputs, outputs, etc.

+40


source


Ok, if you have to do this, then you should. However, you can try to talk to someone who is forcing you to do this so that you can use the UnhandledException event of the AppDomain class . It will provide you with notification of every uncaught exception in any method before it is communicated to the user. Since you can also get the stack trace from the exception object, you can tell exactly where each exception occurs. This is a much better solution than using code with exception handlers all over the place.

With that said, if I had to do this, I would use some regex to identify the start and end of each method, and use it to insert some sort of exception handler all over the place. The trick to writing a regex for this case would be to define group balancing, explained more in the MSDN documentation here . There is also an example of using balancing groups here .

+12


source


Perhaps whoever came up with this requirement doesn't understand that you can still catch all exceptions (above) without putting a try in every function. You can see an example on how to catch all unhandled exceptions here . I think this is a much better solution as you can do something with the exception and report it rather than blindly burying all exceptions, making it extremely difficult to track errors.

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

+3


source


See my answer here , which outlines some of the performance tradeoffs you will have to live with if you use "gotta catch em all" exception handling.

As Scott said, the best way to do the same is with the UnhandledException event. I think jeff actually discussed this issue in an early SO podcast.

+3


source


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

However, if the gods are at a high pointer to be executed, see my answer to this question Get method content from cs file

+2


source


First of all, I am with StingyJack and Binary Worrier. There's good reasons for exceptions not caught by default. If you really want to catch exceptions and die a little better, you can put a try-catch block around the call Application.Run()

and work from there.

When working with external sources (files, internet, etc.), you need to (usually) catch certain exceptions (bad connection, missing file, blah blah). However, in my book, an exception elsewhere means either 1) error, 2) faulty logic, or 3) bad data validation ...

Finally, and not to fully answer your question, are you sure you want to do this?

+2


source


I wanted to write this as an answer to all the answers, then you can find out through the RSS question; the requirement comes from our technical manager: here's the reason: we don't need to figure out which func has problems in production code, any problem was reported as a warning, we put unique code in the ecery catch block and we see where the problem is. It knows there is global error handling, but that doesn't help in this scenario, and the stacktrace is not propagated in release mode, so it requires a try catch block like this:

everyMethod(...){
    try
    {
    ..
    catch(Exception e)
    {
       RaiseAlert(e.Message.. blabla)
    }
}

      

+1


source


If you put a call to RaiseAlert in all methods, you can end up with erroneous stacks that will be very confusing if not inaccurate if you use reusable methods. The logging method should really only need events or the topmost method (s). If someone insists that exception handling should be in every method, they don't understand exception handling.

After a couple of years, we implemented the practice of handling exceptions in every case, and one developer read it as "every method". When they were finished, we had weeks to cancel because no exceptions were reproduced. I assume they knew better than you do, but never doubted the validity of their interpretation.

The AppDomain.UnhandledException implementation is a good fallback, but your only way to use this method is to kill the application after registering the exception. You need to write a global exception handler to prevent this.

+1


source


so here is an example for those interested; 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);
            }
        }

      

+1


source


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

Although such demands are really evil.

0


source


If you really need to , why would you need to fix the source code when you can directly compile the executable / library

Have a look at Cecil (see website ). It is a library that allows you to directly modify the bytecode using this approach, your whole problem can be solved in a few hundred lines of C # code.

0


source


Since you are posting a question here, I'm sure this is one of those things you just have to do. So instead of banging your head against an unshakable wall, why not do what Scott suggested and use the AppDomain event handler. You will meet the requirements without wasting hours on quality billable hours doing grunt work. I'm sure that once you tell your boss how long to check for each file update, using an event handler will be no problem!

0


source


So, you really don't want to put the same exact try-catch block in every function, right? You will have to adapt every try to every feature. Wow! This seems like a long way to "simplify" debugging.

If a user reports a bug in production, why can't you just start Visual Studio and reproduce the steps and debug?

0


source


If you absolutely need to add a try / catch block for each method and scott's answer (AppDomain.UnhandledException) is not enough, you can also look at interceptors. I believe the Castle project has a pretty good implementation of method interceptors.

0


source


If you really need to do this, an alternative to wrapping the exception every time would be to use Exception.Data to capture additional information and then reverse engineer 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 simply dump the contents of ex.Data to get all the extra information you might want. This allows you to put filenames, useragents, ... and any other useful information in the .Data collection to understand why the exception occurred.

0


source


I have done some research work requiring parsing C # code about 2 years ago and found that the SharpDevelop project has source code that does it really well. If you checked out the SharpDevParser project (this was two years ago, it is not clear if the project name is the same as the source code base), you can use the parser object like this:

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

      

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

0


source


I was helping a friend find a memory leak in a C # XNA game he was writing. I suggested giving it a try and see how many times each method was called. To keep counting, I wrote a python script that added 2 lines to update the dictionary with details.

Basically I wrote a python script to modify some 400 ~ 2 line methods. This code might help someone to do more things like the weird thing the OP wanted.

The code uses the path configured on line 3 and iterates recursively when processing .cs files. It also executes subdirectories.

When it finds a cs file, it looks for method declarations, it tries to be as careful as possible. MAKE A BACKUP - I AM NOT RESPONSIBLE IF MY script VIOLATES YOUR CODE !!!

import os, re

path="D:/Downloads/Dropbox/My Dropbox/EitamTool/NetworkSharedObjectModel"
files = []

def processDir(path, files):
    dirList=os.listdir(path)
    for fname in dirList:
        newPath = os.path.normpath(path + os.sep + fname)
        if os.path.isdir(newPath):
            processDir(newPath, files)
        else:
            if not newPath in files:
                files.append(newPath)
                newFile = handleFile(newPath)
            if newPath.endswith(".cs"):
                writeFile(newPath, newFile)

def writeFile(path, newFile):
    f = open(path, 'w')
    f.writelines(newFile)
    f.close()

def handleFile(path):
    out = []
    if path.endswith(".cs"):
        f = open(path, 'r')
        data = f.readlines()
        f.close()

        inMethod = False
        methodName = ""
        namespace = "NotFound"
        lookingForMethodDeclerationEnd = False
        for line in data:
            out.append(line)
            if lookingForMethodDeclerationEnd:
                strippedLine = line.strip()
                if strippedLine.find(")"):
                    lookingForMethodDeclerationEnd = False
            if line.find("namespace") > -1:
                namespace = line.split(" ")[1][0:-2]
            if not inMethod:
                strippedLine = line.strip()
                if isMethod(strippedLine):
                    inMethod = True
                    if strippedLine.find(")") == -1:
                        lookingForMethodDeclerationEnd = True
                    previousLine = line
            else:
                strippedLine = line.strip()
                if strippedLine == "{":
                    methodName = getMethodName(previousLine)
                    out.append('            if (!MethodAccess.MethodAccess.Counter.ContainsKey("' + namespace + '.' + methodName + '")) {MethodAccess.MethodAccess.Counter.Add("' + namespace + '.' + methodName + '", 0);}')
                    out.append("\n" + getCodeToInsert(namespace + "." + methodName))
                    inMethod = False
    return out

def getMethodName(line):
    line = line.strip()
    lines = line.split(" ")
    for littleLine in lines:
        index = littleLine.find("(")
        if index > -1:
            return littleLine[0:index]


def getCodeToInsert(methodName):
    retVal = "          MethodAccess.MethodAccess.Counter[\"" + methodName + "\"]++;\n"
    return retVal

def isMethod(line):
    if line.find("=") > -1 or line.find(";") > -1 or line.find(" class ") > -1:
        return False
    if not (line.find("(") > -1):
        return False
    if line.find("{ }") > -1:
        return False
    goOn = False
    if line.startswith("private "):
        line = line[8:]
        goOn = True
    if line.startswith("public "):
        line = line[7:]
        goOn = True
    if goOn:
        return True
    return False

processDir(path, files)

      

0


source







All Articles