Excel VSTO中的Form.Show(IWin32Window)方法导致应用程序关闭时出现ThreadAbortException

时间:2014-05-07 13:35:26

标签: c# winforms excel vsto

我有一个excel插件,我有一个表格,我想成为excel窗口的前面。为此,我在excel功能区菜单按钮上使用NativeWindow,如下所示:

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

}

如果我在退出excel之前关闭我的表单一切正常,这非常有效。但是如果用户想要在不关闭打开的表单的情况下退出excel,则会发生ThreadAbortException异常:

未处理的类型&#39; System.Threading.ThreadAbortException&#39;发生在System.Windows.Forms.dll

其他信息:线程正在中止。

为了解决这个问题,我尝试了以下代码,但没有工作:

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

我在哪里可以犯错?

2 个答案:

答案 0 :(得分:3)

我使用IWin32Window界面而不是NativeWindow来解决问题:

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

    IntPtr _windowHandle;

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

在此之后,我更改了下面的表单初始化代码:

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

答案 1 :(得分:0)

编辑:我在这里添加我的答案b \ c用户答案是一个解决方法,而不是解释问题的可能性:我建议查看解决方案微软推出并根据您的需要进行修改

在此处查看我的回答:https://stackoverflow.com/a/38157476/ 根据您正在尝试收听的窗口,您可能会破坏非托管窗口监听器,遗憾的是NativeWindow.ReleaseHandle不知道如何恢复子类窗口链,而是替换您使用User32更改的窗口wndproc!DefWindowProc [this]将导致应用程序崩溃或挂起。