简体   繁体   English

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

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

I have an excel add-in and i have a form that i would like to be front of excel window. 我有一个Excel加载项,并且我有一个想要成为Excel窗口前面的表格。 I use NativeWindow for this purpose on excel ribbon menu button like this: 为此,我在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);
    }

}

If I close my form before exit from excel everything is ok, this works very well. 如果我在退出excel之前关闭表单,一切正常,那么效果很好。 But if user wants to exit from excel without close the opened form then ThreadAbortException exception occurs: 但是,如果用户要退出excel而不关闭打开的表单,则会发生ThreadAbortException异常:

An unhandled exception of type 'System.Threading.ThreadAbortException' occurred in System.Windows.Forms.dll System.Windows.Forms.dll中发生类型为'System.Threading.ThreadAbortException'的未处理异常

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? 我在哪里犯错?

I resolve the problem with use IWin32Window interface instead NativeWindow : 我使用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; }
    }
}

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

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. 编辑:我在这里添加我的答案b \\ c用户答案是一种变通方法,而不是对可能出现的问题的解释:我建议检查Microsoft提出的解决方案并根据您的需要进行修改。

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/a/38157476/取决于您尝试在哪个窗口上监听您,可能是在伪造非托管窗口监听器,不幸的是,NativeWindow.ReleaseHandle不知道如何还原子类化窗口链,而是用User32!DefWindowProc [this]替换您更改的Windows wndproc,这将导致应用程序崩溃或挂起。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM