<p>I was just working on fixing up exception handling in a .NET 2.0 app, and I stumbled onto some weird issue with <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.application.threadexception.aspx" rel="nofollow noreferrer">Application.ThreadException</a>.</p>

<p>What I want is to be able to catch all exceptions from events behind GUI elements (e.g. button_Click, etc.). I then want to filter these exceptions on 'fatality', e.g. with some types of Exceptions the application should keep running and with others it should exit.</p>

<p>In another .NET 2.0 app I learned that, by default, only in debug mode the exceptions actually leave an Application.Run or Application.DoEvents call. In release mode this does not happen, and the exceptions have to be 'caught' using the Application.ThreadException event.</p>

<p>Now, however, I noticed that <strong>the exception object passed in the ThreadExceptionEventArgs of the Application.ThreadException event is always the innermost exception in the exception chain</strong>. For logging/debugging/design purposes I really want the entire chain of exceptions though. It isn't easy to determine what external system failed for example when you just get to handle a SocketException: when it's wrapped as e.g. a NpgsqlException, then at least you know it's a database problem.</p>

<p><strong>So, how to get to the entire chain of exceptions from this event?</strong> Is it even possible or do I need to design my excepion handling in another way?</p>

<p>Note that I do -sort of- have a <a href="https://stackoverflow.com/questions/61366/rolling-your-own-message-loop-any-pitfalls">workaround</a> using <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.application.setunhandledexceptionmode.aspx" rel="nofollow noreferrer">Application.SetUnhandledExceptionMode</a>, but this is far from ideal because I'd have to roll my own message loop.</p>

<p>EDIT: to prevent more mistakes, <strong>the GetBaseException() method does NOT do what I want</strong>: it just returns the innermost exception, while the only thing I already have is the innermost exception. I want to get at the outermost exception!</p>

[{'answer_id': 61363, 'author': 'Leo Moore', 'author_id': 6336, 'author_profile': 'https://Stackoverflow.com/users/6336', 'pm_score': 0, 'selected': False, 'text': '<p>Have you tried the Exception.GetBaseException Method? This returns the exception which created the Application.TreadException. You could then use the same process to go up the chain to get all exceptions.</p>\n\n<p><a href="http://msdn.microsoft.com/en-us/library/system.exception.getbaseexception.aspx" rel="nofollow noreferrer">exception.getbaseexception Method</a></p>\n'}, {'answer_id': 61647, 'author': 'Leo Moore', 'author_id': 6336, 'author_profile': 'https://Stackoverflow.com/users/6336', 'pm_score': -1, 'selected': False, 'text': "<p>According to the MSDN documentation:</p>\n\n<p><em>When overridden in a derived class, returns the Exception that is the root cause of one or more subsequent exceptions.</em> </p>\n\n<pre><code>    Public Overridable Function GetBaseException() As Exception\n        Dim innerException As Exception = Me.InnerException\n        Dim exception2 As Exception = Me\n        Do While (Not innerException Is Nothing)\n            exception2 = innerException\n            innerException = innerException.InnerException\n        Loop\n        Return exception2\n    End Function\n</code></pre>\n\n<p>You could use a variation on this to parse the exception chain. </p>\n\n<pre><code>Public Sub LogExceptionChain(ByVal CurrentException As Exception)\n\n    Dim innerException As Exception = CurrentException.InnerException\n    Dim exception2 As Exception = CurrentException\n\n    Debug.Print(exception2.Message) 'Log the Exception\n\n    Do While (Not innerException Is Nothing)\n\n        exception2 = innerException\n        Debug.Print(exception2.Message) 'Log the Exception\n\n        'Move to the next exception\n        innerException = innerException.InnerException\n    Loop\n\nEnd Sub\n</code></pre>\n\n<p>This would strike me as exactly what you are looking for.</p>\n"}, {'answer_id': 308388, 'author': 'Vincent Van Den Berghe', 'author_id': 39259, 'author_profile': 'https://Stackoverflow.com/users/39259', 'pm_score': 1, 'selected': False, 'text': '<p>I tried to reproduce this behaviour (always getting the innermost exception),<br>\nbut I get the exception I expect, with all InnerExceptions intact.</p>\n\n<p>Here is the code I used to test:</p>\n\n<pre><code>   Private Shared Sub Test1()\n      Try\n         Test2()\n      Catch ex As Exception\n         Application.OnThreadException(New ApplicationException("test1", ex))\n      End Try\n   End Sub\n\n   Private Shared Sub Test2()\n      Try\n         Test3()\n      Catch ex As Exception\n         Throw New ApplicationException("test2", ex)\n      End Try\n   End Sub\n\n   Private Shared Sub Test3()\n      Throw New ApplicationException("blabla")\n   End Sub\n\nPrivate Shared Sub HandleAppException(ByVal sender As Object, ByVal e As ThreadExceptionEventArgs)\n...\nEnd Sub\n</code></pre>\n\n<p>Sub HandleAppException handles Application.ThreadException. The Test1() method is called first.<br>\nThis is the result (e As ThreadExceptionEventArgs) I get in HandleAppException:</p>\n\n<p><a href="http://mediasensation.be/dump/?download=ThreadException.jpg" rel="nofollow noreferrer">ThreadException http://mediasensation.be/dump/?download=ThreadException.jpg</a></p>\n\n<p>If you just catch and (re)throw exceptions, no InnerExceptions wil show up, but it will be appended to the Exception.<strong>StackTrace</strong>, like this:</p>\n\n<blockquote>\n  <p>at SO.Test3() in Test.vb:line 166<br>\n  at SO.Test2() in Test.vb:line 159<br>\n  at SO.Test1() in Test.vb:line 151</p>\n</blockquote>\n'}, {'answer_id': 308423, 'author': 'Tamas Czinege', 'author_id': 8954, 'author_profile': 'https://Stackoverflow.com/users/8954', 'pm_score': 1, 'selected': False, 'text': '<p>Normally, you only lose the whole exception chain except for the base exception in a Application.ThreadException exception handler if the exception happened in an other thread.</p>\n\n<p>From the <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.application.threadexception.aspx" rel="nofollow noreferrer">MSDN Library</a>:</p>\n\n<blockquote>\n  <p>This event allows your Windows Forms\n  application to handle otherwise\n  unhandled exceptions that occur in\n  <strong>Windows Forms</strong> threads. Attach your\n  event handlers to the ThreadException\n  event to deal with these exceptions,\n  which will leave your application in\n  an unknown state. Where possible,\n  exceptions should be handled by a\n  structured exception handling block.</p>\n</blockquote>\n\n<p>Solution: If you do threading, make sure that all your threads/async calls are in a try/catch block. Or as you said, you can play with Application.SetUnhandledExceptionMode.</p>\n'}, {'answer_id': 1228834, 'author': 'Ashley Tate', 'author_id': 50277, 'author_profile': 'https://Stackoverflow.com/users/50277', 'pm_score': 3, 'selected': True, 'text': '<p>This question is more usefully phrased and answered here: </p>\n\n<p><a href="https://stackoverflow.com/questions/347502/why-does-the-inner-exception-reach-the-threadexception-handler-and-not-the-actual">Why does the inner exception reach the ThreadException handler and not the actual thrown exception?</a></p>\n'}, {'answer_id': 1871195, 'author': 'iszzypop', 'author_id': 227639, 'author_profile': 'https://Stackoverflow.com/users/227639', 'pm_score': 1, 'selected': False, 'text': '<p>Just discovered something interesting.  Different GUI events will get you different results.  An exception thrown from a Form.Shown event handler will result in Application.ThreadException catching the inner-most exception, but the exact same code run in the Form.Load event will result in the <em>outer-most</em> exception getting caught in Application.ThreadException.</p>\n'}, {'answer_id': 28890916, 'author': 'Queue', 'author_id': 4639188, 'author_profile': 'https://Stackoverflow.com/users/4639188', 'pm_score': 1, 'selected': False, 'text': "<p>Based on some of the information in this chain, I used UnhandledExceptionMode.ThrowException as opposed to UnhandledExceptionMode.CatchException. I then catch the exception outside the form's Run() and this gives me the entire chain of exceptions.</p>\n"}]
['https://Stackoverflow.com/questions/61354', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/5422/']