Метод Form.Show(IWin32Window) в Excel VSTO, вызывающий исключение ThreadAbortException при закрытии приложения

У меня есть надстройка Excel, и у меня есть форма, которую я хотел бы быть перед окном Excel. я использую NativeWindow Для этого на ленте Excel кнопка меню выглядит так:

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 исключение происходит:

Произошло необработанное исключение типа "System.Threading.ThreadAbortException" в 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 ответа

Решение

Я решаю проблему с использованием 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);
}

Изменить: я добавляю свой ответ здесь, потому что пользовательский ответ - обходной путь, а не объяснение вероятной проблемы: я рекомендую проверить решение, выпущенное Microsoft, и изменить его для ваших нужд.

см. мой ответ здесь: /questions/25388003/alternativyi-nativewindow-dlya-sozdaniya-podklassov/25388020#25388020 зависимости от того, какое окно вы пытаетесь прослушать, возможно, портит неуправляемый обработчик окон и, к сожалению, NativeWindow.ReleaseHandle не знает, как восстановить окно подклассов. цепочку и заменяет Windows wndproc, который вы изменили на User32!DefWindowProc[this], что приведет к сбою или зависанию приложения.

Другие вопросы по тегам