2

When firing up my Excel add-in, I preserve a handle to an Excel window using the following code:

ExcelWindow = new NativeWindow();
ExcelWindow.AssignHandle(new IntPtr(Application.Hwnd));

When it comes to releasing a handle, I try to do it while shutting down:

private void ThisAddInShutdown(object sender, EventArgs e)
{
  try
  {
    ExcelWindow.ReleaseHandle();
  } 
  catch
  {

  }
}

When exiting excel in Debug mode, everything works fine. Unfortunately, when running this code on a production system, I get a crash, with no ability to debug what's going on. I get a 'windows is checking this problem' window, subsequently it disappears, and that's it.

It's really not a big deal, but I don't want to annoy the users with something like this. So, does anyone have any idea what it could be and how I could debug this? Thanks.

Dmitri Nesteruk
  • 23,067
  • 22
  • 97
  • 166
  • Try catching the exception (*e.g. `catch(Exception ex)` and write it to a log file or database*). You could even just use a trace output statement and **WinDbg**. I'd first start with capturing what the source error is and then determine how best to handle it. – SliverNinja - MSFT Feb 04 '13 at 20:19
  • I don't know if you noticed but I have a catch-all around the statement that causes the exception. That doesn't work. – Dmitri Nesteruk Feb 04 '13 at 20:55
  • Please share what the actual `Exception` is. Make sure you wrap up any code you have in your plugin in a try/catch. Does the `Exception`/crash go away if you remove the `ReleaseHandle` call? Without knowing the actual exception, we can't help you troubleshoot. – SliverNinja - MSFT Feb 05 '13 at 14:51

1 Answers1

1

My solution:

public partial class ThisAddIn
{
    ExcelWindow window;

    private void ThisAddIn_Startup(object sender, System.EventArgs e)
    {
        window = new ExcelWindow();

        Application.WorkbookBeforeClose += new Excel.AppEvents_WorkbookBeforeCloseEventHandler(Application_WorkbookBeforeClose);
        Application.WorkbookActivate += new Excel.AppEvents_WorkbookActivateEventHandler(Application_WorkbookActivate);
        Application.WorkbookDeactivate += new Excel.AppEvents_WorkbookDeactivateEventHandler(Application_WorkbookDeactivate);
    }

    void Application_WorkbookDeactivate(Excel.Workbook Wb)
    {
        window.ReleaseHandle();
    }

    void Application_WorkbookActivate(Excel.Workbook Wb)
    {
        window.AssignHandle(new IntPtr(Application.Hwnd));
    }

    void Application_WorkbookBeforeClose(Excel.Workbook Wb, ref bool Cancel)
    {
        if (Application.Workbooks.Count > 1 || window.Handle == IntPtr.Zero) return;
        Cancel = true;
        window.ReleaseHandle();
        Dispatcher.CurrentDispatcher.BeginInvoke(new MethodInvoker(Application.Quit), null);
    }

    private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
    {
    }

    #region VSTO generated code

    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InternalStartup()
    {
        this.Startup += new System.EventHandler(ThisAddIn_Startup);
        this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
    }

    #endregion
}
  • Where does the `Dispatcher` come from? – Dmitri Nesteruk Apr 29 '13 at 13:50
  • It is important to invoke the close-command to the main-thread again. So the ReleaseHandle is done in the meantime when the function ends. And after all the invoke will execute. The Dispatcher is only for invoking to the main-thread. [MSDN Dispatcher](http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.currentdispatcher(v=vs.100).aspx) – Master-20000 Apr 30 '13 at 14:12