Domanda

You are apparently able to rethrow an Exception without discarding the stack trace in .NET.

However it doesn't appear to be working.

Basic usage I'm following is thus:

    [WebMethod]
    public void ExceptionTest()
    {
        try
        {
            throw new Exception("An Error Happened");
        }
        catch (Exception ex)
        {
            evlWebServiceLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
            throw;
        }
    }

Problem is, the line number in the exception in the line of the throw; line, not the original throw new line.

I've tested it in a simple exe project and without the logging to the windows log line. It doesn't make any difference, the stack trace always has the wrong line number in it, making it less than useful.

Why is it doing this? How do I do it correctly?

È stato utile?

Soluzione

You do not lose original exception if you place it in an inner exception.

[WebMethod]
public void ExceptionTest()
{
    try
    {
        throw new Exception("An Error Happened");
    }
    catch (Exception ex)
    {
        evlWebServiceLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
        throw new Exception("Your message", ex);
    }
}

Altri suggerimenti

I've used the following for years. Don't know if there a less "dodgy" way to achieve it in more up to date .Net frameworks though:

public void PreserveStackTrace(Exception ex)
{
    MethodInfo preserve = ex.GetType().GetMethod("InternalPreserveStackTrace",
                                                 BindingFlags.Instance | BindingFlags.NonPublic);
    preserve.Invoke(ex,null);
}

To use this:

[WebMethod]
public void ExceptionTest()
{
    try
    {
        throw new Exception("An Error Happened");
    }
    catch (Exception ex)
    {
        evlWebServiceLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
        PreserveStackTrace(ex);
        throw ex;
    }
}

Update: based on @dcastro's comment, I'd fancy an extension method in 4.5 (in < 4.5 it could still be an extension wrapping the method above):

public static void ReThrow(this Exception ex)
{
    var exInfo = ExceptionDispatchInfo.Capture(ex); 
    exInfo.Throw();
}

So you'd just have:

    catch (Exception ex)
    {
        evlWebServiceLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
        ex.ReThrow();
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top