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

拥有回忆 提交于 2020-01-02 09:24:32

问题


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?


回答1:


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);
}



回答2:


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.



来源:https://stackoverflow.com/questions/23519382/form-showiwin32window-method-in-excel-vsto-causing-threadabortexception-on-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!