locked
Global Exception Handler for VS 2008 Excel addin RRS feed

  • Question

  • Hi Folks,

    I have written a very large VS 2008 Excel addin (in vb.net) and would like to exit smoothly if anything goes wrong. The addin uses external propriety classes, forms and modules and is run from a custom ribbon tab. I have searched the internet but haven't quite found out how to implement a Global Exception Handler in vb.net.

    Hope someone can assist!

    Bernie


    bb


    • Edited by Bernie Ok Friday, February 10, 2012 3:15 AM
    Friday, February 10, 2012 3:13 AM

Answers

  • I use try...catch blocks everywhere there's the remotest possibility of an exception. In addition to that "belt", I also implement the 2 handlers you were looking at to catch other exceptions where possible ("suspenders").
     
    It's not foolproof, you can have exceptions in libraries such as kernel32 and there's nothing you can do about it. But you do as much as you can, unfortunately I know of no way to make things completely bulletproof.

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Bernie Ok" <=?utf-8?B?QmVybmllIE9r?=> wrote in message news:cb720a52-12d4-4445-85da-14c696d7d051...

    Thank you Ken,

    I think we are on the same page. I am limited in my knowledge of the .net framework so please bear with me.

    You speak of 'belt and suspenders exception handlers'.

    I wonder if you could expand on this expression a bit. Does this mean use lots of Try .. Catch ... blocks all over the place?

    My solution has about 20 forms, each activated from the ribbon. Each one of these forms does considerable and sometimes complex numeric calculations. Is it possible to wrap a whole form class inside of a Try ... Catch block (perhaps in the ribbon code where the form is activated)?. My solution also has a huge module with many functions and subroutines that are called by all of the forms. Is it possible to wrap a whole module inside of a Try .... Catch block?

    I guess what I am getting at here is that I am interested in a general strategy that makes my solution bomb proof (or bomb out proof). Any specific code that might be of relevance is most welcome.

    Thanks,

    Bernie


    bb


    Ken Slovak MVP - Outlook
    • Marked as answer by Bernie Ok Friday, February 17, 2012 9:20 PM
    Friday, February 17, 2012 2:29 PM

All replies

  • i think you should handle 2 .net events:

    System.Windows.Forms.Application.ThreadException and AppDomain.CurrentDomain.UnhandledException.

    Friday, February 10, 2012 8:43 AM
  • Thanks DamianD,

    I believe that you are correct but I need more assistance:

    (1) Where do I implement a Global Exception Handler in the addin?

    (2) How do I implement a Global Exception Handler in the addin? For example, in the event of an exception I would like to show a messagebox to the user that indicates that an exception has occurred, what type of exception has occurred and where the exception occurred. Also, any other information that might enable the developer to rectify the problem.

    Thanks,

    Bernie


    bb


    • Edited by Bernie Ok Friday, February 10, 2012 10:56 PM
    Friday, February 10, 2012 10:49 PM
  • usually i put code that registers to those events in add-in startup event. There, is any of those events are called, i display error form, log message to log file and give option to send error package to me (easiest way when developing outlook addin).
    Monday, February 13, 2012 3:28 PM
  • Thanks again DamianD,

    I agree, the code should go in the Me.Startup event handler. But I still don't know exectly how to code a Global Event handler. I have seen some examples written in cs but I am working in vb. Also, I just don't properly understand the examples that I have seen. I would also like to display an error form, log the message to a log file and give the option to send error package to me. Any chance that someone has a code snippet (hopefully well documented) that I can work with?

    Thanks,

    Bernie


    bb

    Monday, February 13, 2012 9:10 PM
  • i also work with c# but converting functions to vb.net is a small task, do not worry.

    private static void RegisterToExceptionEvents()
            {
                System.Windows.Forms.Application.ThreadException += ApplicationThreadException;
    
                AppDomain.CurrentDomain.UnhandledException += CurrentDomainUnhandledException;
            }
    
            private static bool _handlingUnhandledException;
            static void CurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
            {
                HandleUnhandledException((Exception)e.ExceptionObject);//there is small possibility that this wont be exception but only when interacting with code that can throw object that does not inherit from Exception
            }
    
            static void ApplicationThreadException(object sender, ThreadExceptionEventArgs e)
            {
                HandleUnhandledException(e.Exception);
            }
    
            private static void HandleUnhandledException(Exception exception)
            {
                if (_handlingUnhandledException)
                    return;
                try
                {
                    _handlingUnhandledException = true;
                    ErrorHandler.HandleFatalError(exception, "Unhandled exception occurred, plug-in will close.");
                }
                finally
                {
                    _handlingUnhandledException = false;
                }
            }

    Tuesday, February 14, 2012 8:49 AM
  • Thanks DamianD,

    I had a go at translating your code to vb.net (see below). It doesn't work and I am sure that I have done something wrong!!

    I put System.Windows.Forms.Application.ThreadException and AppDomain.CurrentDomain.UnhandledException into the Me.Startup subroutine. I assume ErrorHandler is a user defined class so I replaced it with an error message. I assume this is the point in the code where we handle the error!! (If not, which class does it belong to?) The fact is I am highly confused and may be simply demonstrating my lack of knowledge of the .net framework.

    Imports System.Threading
    
    Public Class ThisAddIn
       Private Shared _handlingUnhandledException As Boolean
    
       Private Sub ThisAddIn_Startup(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Startup
          AddHandler System.Windows.Forms.Application.ThreadException, AddressOf ApplicationThreadException
          AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf CurrentDomainUnhandledException
       End Sub
    
       Private Shared Sub CurrentDomainUnhandledException(ByVal sender As Object, ByVal e As UnhandledExceptionEventArgs)
          HandleUnhandledException(DirectCast(e.ExceptionObject, Exception))
          'there is small possibility that this wont be exception but only when interacting with code that can throw object that does not inherit from Exception
       End Sub
    
       Private Shared Sub ApplicationThreadException(ByVal sender As Object, ByVal e As ThreadExceptionEventArgs)
          HandleUnhandledException(e.Exception)
       End Sub
    
       Private Shared Sub HandleUnhandledException(ByVal exception As Exception)
          If _handlingUnhandledException Then
             Return
          End If
          Try
             _handlingUnhandledException = True
             'ErrorHandler.HandleFatalError(exception, "Unhandled exception occurred, plug-in will close.")
             MessageBox.Show("Unhandled Exception Error" + Chr(13) + exception.Message, _
                             "", MessageBoxButtons.OK, MessageBoxIcon.Error)
          Finally
             _handlingUnhandledException = False
          End Try
       End Sub
    
    End Class
    Many Thanks

    Bernie


    bb

    Tuesday, February 14, 2012 11:24 PM
  • Seems ok to me. Did you verify using debugger that your ThisAddin_Startup event handler is actually called? If it is, describe in more detail situation where it does not work.
    Wednesday, February 15, 2012 9:25 AM
  • I do not believe that you can use the threadException and UnhandledException events in a VSTO addin.  This is because VSTO loads its layer in an AppDomain, then creates another AppDomain for your code. 

    In order to connect up an exception handler of this type, I am pretty sure you would need to locate the main AppDomain and register with those event handlers. 

    • Proposed as answer by Kiran Kumnoor Friday, August 19, 2016 7:22 PM
    Wednesday, February 15, 2012 8:54 PM
  • Thank you John,

    I am getting out of my depth here. Can you point to any examples where this is implemented. I am open to any suggestions. My Excel addin has a number of forms activated from the ribbon so that any Global Exception handler would need to handle any exception occuring in any of these forms.

    Regards,

    Bernie


    bb

    Wednesday, February 15, 2012 10:20 PM
  • Hi

    much to my suprise, John is right, those events do not capture unhandled exceptions (to my defence i can only say that i think they worked on 2003 and i haven't touched that code since). I will look at that code again later today and try to come up with something for you.

    Thursday, February 16, 2012 10:41 AM
  • And small update - as long as exception is not thrown from Startup event handler - ThreadException handler works just fine (tested on outlook UI event handler that shows winforms window and throws unhandled exception when clicking button there).

    Thursday, February 16, 2012 3:40 PM
  • Thankyou DamienD,

    unfortunately I still cannot get the Global Exception handler to work. I use the code as shown in the Me.Startup subroutine posted on Feb 14. I then add a form with a button to my solution which is activated from the Excel ribbon. The code behind this form is as follows:

    Public Class frmTestForm
       Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
          Dim x As Integer = "x"
       End Sub
    End Class

    When I click Button1 on the form the program bombs out with an InvalidCastException. But the exception is not handled by the Global Exception handler.

    Thanks,

    Bernie


    bb

    Thursday, February 16, 2012 9:30 PM
  • First, you need error handling. Use Try...Catch blocks.
     
    Second, you are doing an invalid cast of a string to an Integer:
     
    Dim x As Integer = "x"

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Bernie Ok" <=?utf-8?B?QmVybmllIE9r?=> wrote in message news:ebdc0c45-409d-43f7-85f3-b4bb3cd2e594...

    Thankyou DamienD,

    unfortunately I still cannot get the Global Exception handler to work. I use the code as shown in the Me.Startup subroutine posted on Feb 14. I then add a form with a button to my solution which is activated from the Excel ribbon. The code behind this form is as follows:

    Public Class frmTestForm
       Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
          Dim x As Integer = "x"
       End Sub
    End Class

    When I click Button1 on the form the program bombs out with an InvalidCastException. But the exception is not handled by the Global Exception handler.

    Thanks,

    Bernie


    bb


    Ken Slovak MVP - Outlook
    Thursday, February 16, 2012 9:41 PM
  • Thanks Ken,

    I am deliberately throwing an InvalidCastException so that I can test the global exception handler. The code for the global exception handler was posted on Feb 14 (see above). I suspect that you may be unclear as to the purpose of this test.

    Regards,

    Bernie


    bb

    Thursday, February 16, 2012 9:54 PM
  • Ah, OK. That code looks quite familiar :)
     
    As was said elsewhere in the thread, neither of those events will fire if the exception is in the VSTO layer, which is in a different AppDomain. Neither will fire in other circumstances too, such as if an error occurs in Excel or Outlook, or the CLR or the VC runtime or ....
     
    You do the best you can, which are those types of belt and suspenders exception handlers. Things like that aren't perfect, their just better than nothing. I've only see those handlers fire a few times in error log examinations over the years, but when they did fire they were quite helpful.

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Bernie Ok" <=?utf-8?B?QmVybmllIE9r?=> wrote in message news:41969b8e-a033-4f89-8b5b-1a0e19e166a0...

    Thanks Ken,

    I am deliberately throwing an InvalidCastException so that I can test the global exception handler. The code for the global exception handler was posted on Feb 14 (see above). I suspect that you may be unclear as to the purpose of this test.

    Regards,

    Bernie


    bb


    Ken Slovak MVP - Outlook
    Thursday, February 16, 2012 10:04 PM
  • Thank you Ken,

    I think we are on the same page. I am limited in my knowledge of the .net framework so please bear with me.

    You speak of 'belt and suspenders exception handlers'.

    I wonder if you could expand on this expression a bit. Does this mean use lots of Try .. Catch ... blocks all over the place?

    My solution has about 20 forms, each activated from the ribbon. Each one of these forms does considerable and sometimes complex numeric calculations. Is it possible to wrap a whole form class inside of a Try ... Catch block (perhaps in the ribbon code where the form is activated)?. My solution also has a huge module with many functions and subroutines that are called by all of the forms. Is it possible to wrap a whole module inside of a Try ... Catch block?

    I guess what I am getting at here is that I am interested in a general strategy that makes my solution bomb proof (or bomb out proof). Any specific code that might be of relevance is most welcome.

    Thanks,

    Bernie


    bb

    Friday, February 17, 2012 12:58 AM
  • I use try...catch blocks everywhere there's the remotest possibility of an exception. In addition to that "belt", I also implement the 2 handlers you were looking at to catch other exceptions where possible ("suspenders").
     
    It's not foolproof, you can have exceptions in libraries such as kernel32 and there's nothing you can do about it. But you do as much as you can, unfortunately I know of no way to make things completely bulletproof.

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Bernie Ok" <=?utf-8?B?QmVybmllIE9r?=> wrote in message news:cb720a52-12d4-4445-85da-14c696d7d051...

    Thank you Ken,

    I think we are on the same page. I am limited in my knowledge of the .net framework so please bear with me.

    You speak of 'belt and suspenders exception handlers'.

    I wonder if you could expand on this expression a bit. Does this mean use lots of Try .. Catch ... blocks all over the place?

    My solution has about 20 forms, each activated from the ribbon. Each one of these forms does considerable and sometimes complex numeric calculations. Is it possible to wrap a whole form class inside of a Try ... Catch block (perhaps in the ribbon code where the form is activated)?. My solution also has a huge module with many functions and subroutines that are called by all of the forms. Is it possible to wrap a whole module inside of a Try .... Catch block?

    I guess what I am getting at here is that I am interested in a general strategy that makes my solution bomb proof (or bomb out proof). Any specific code that might be of relevance is most welcome.

    Thanks,

    Bernie


    bb


    Ken Slovak MVP - Outlook
    • Marked as answer by Bernie Ok Friday, February 17, 2012 9:20 PM
    Friday, February 17, 2012 2:29 PM
  • Thanks for all of your help Ken.

    Have a great day :)

    Best,

    Bernie


    bb

    Friday, February 17, 2012 9:20 PM