Form.Show(IWin32Window) method in Excel VSTO causing ThreadAbortException on application close

StackOverflow https://stackoverflow.com/questions/23519382

  •  17-07-2023
  •  | 
  •  

Question

I have an excel add-in and i have a form that i would like to be front of excel window. I use NativeWindow for this purpose on excel ribbon menu button like this:

public partial class MyRibbonMenu
{
    public List<Form> Forms = new List<Form>();

    private void button1_Click(object sender, RibbonControlEventArgs e)
    {
        // initialize form
        Form frm = new Form();
        frm.Text = "Test Form";
        Forms.Add(frm);

        // create the native window handle
        NativeWindow nw = new NativeWindow();
        IntPtr iptr = new IntPtr(Globals.ThisAddIn.Application.Hwnd);
        nw.AssignHandle(iptr);

        // when close the form release the handle
        frm.FormClosed += (sender2, e2) =>
        {
            Forms.Remove(frm);
            nw.ReleaseHandle();
        };

        // show with owner
        frm.Show(nw);
    }

}

If I close my form before exit from excel everything is ok, this works very well. But if user wants to exit from excel without close the opened form then ThreadAbortException exception occurs:

An unhandled exception of type 'System.Threading.ThreadAbortException' occurred in System.Windows.Forms.dll

Additional information: Thread was being aborted.

For resolve this problem I have tried the following code but didn't work:

private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
    var frms = Globals.Ribbons.MyRibbonMenu.Forms.ToArray();
    foreach (var frm in frms)
    {
        frm.Close();
    }
}

Where can I making a mistake?

Was it helpful?

Solution

I resolve the problem with use IWin32Window interface instead NativeWindow:

public class Win32Window : System.Windows.Forms.IWin32Window
{
    public Win32Window(int windowHandle)
    {
        _windowHandle = new IntPtr(windowHandle);
    }

    IntPtr _windowHandle;

    public IntPtr Handle
    {
        get { return _windowHandle; }
    }
}

After this I change form initialize code below:

private void button1_Click(object sender, RibbonControlEventArgs e)
{
    // initialize form
    var frm = new Form();
    frm.FormBorderStyle = FormBorderStyle.FixedSingle;
    frm.MinimizeBox = false;
    frm.MaximizeBox = false;
    frm.Text = "Test Form";
    frm.StartPosition = FormStartPosition.CenterScreen;
    Forms.Add(frm);

    // create the native window handle
    var nw = new Win32Window(Globals.ThisAddIn.Application.Hwnd);

    // show with owner
    frm.Show(nw);
}

OTHER TIPS

Edit: I'm adding my answer here b\c the user answer is a work around and not an explanation of what the problem likely is: i recommend checking out the solution microsoft put out and modify it for your needs.

see my answer here: https://stackoverflow.com/a/38157476/ depending on what window you are trying to listen in on you maybe mucking up an unmanaged window listener and unfortunately NativeWindow.ReleaseHandle does not know how to restore the subclassing window chain and instead replaces the windows wndproc you altered with User32!DefWindowProc[this] which will cause an application crash or hang.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top