Модальный MessageBox на другом дескрипторе процесса может заблокировать целевой процесс - PullRequest
1 голос
/ 11 августа 2009

Если я показываю MessageBox как модальное окно в другом процессе, он работает просто отлично, пока моя программа продолжает отвечать. Если он закрыт или завершен во время отображения MessageBox, окна, которые получили MessageBox, будут заблокированы (но все еще отвечают), и его придется завершать с помощью диспетчера задач.

Вот пример кода, демонстрирующий, что:

using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;

namespace TestMessageBox
{
    class Program
    {
        private WindowWrapper notepad;

        Program(IntPtr handle)
        { 
            notepad = new WindowWrapper(handle); 
        }

        static void Main(string[] args)
        {
            Process[] procs = Process.GetProcessesByName("notepad");
            if (procs.Length > 0)
            {
                Console.WriteLine("Notepad detected...");
                Program program = new Program(procs[0].MainWindowHandle);
                Thread thread = new Thread(new ThreadStart(program.ShowMessage));
                thread.IsBackground = true;
                thread.Start();
                Console.Write("Press any key to end the program and lock notepad...");
                Console.ReadKey();
            }
        }

        void ShowMessage()
        { 
            MessageBox.Show(notepad, "If this is open when the program ends\nit will lock up notepad..."); 
        }
    }

    /// <summary>
    /// Wrapper class so that we can return an IWin32Window given a hwnd
    /// </summary>
    public class WindowWrapper : System.Windows.Forms.IWin32Window
    {
        public WindowWrapper(IntPtr handle)
        { 
            _hwnd = handle; 
        }
        public IntPtr Handle
        { 
            get { return _hwnd; } 
        }
        private IntPtr _hwnd;
    }

}

Как этого избежать?

1 Ответ

1 голос
/ 11 августа 2009

Акт отображения модального диалога отключает родительское окно диалога (окно Notepad в вашем примере). Когда модальное диалоговое окно закрывается, родительское окно снова включается.

Если ваша программа умирает до того, как она повторно активирует окно, это окно никогда не будет повторно включено - это зависит от потока, который показывает диалоговое окно для повторного включения родителя. (В вашем примере это происходит в MessageBox.Show(), после того, как пользователь нажмет OK или что-то еще.)

Единственный способ сделать эту работу - это иметь второй процесс, в обязанности которого входило возвращать вещи такими, какими они должны быть, если процесс создания модального диалога преждевременно умирает, но это ужасно. И это все еще не пуленепробиваемый - что, если процесс наблюдателя тоже умирает?

...