另一个进程上的模态消息框 句柄可能会锁定目标进程

发布于 2024-07-30 06:23:16 字数 1665 浏览 2 评论 0原文

如果我将 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;
    }

}

如何避免这种情况?

If I show a MessageBox as modal of a window on another process, it works just fine as long as my program remains responding. If it is closed or terminated while the MessageBox is showing the windows that received the MessageBox will be locked (but still responding) and it will have to be finalized via Task Manager.

Here is a sample code to demonstrate that:

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

}

How to avoid that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

拥抱影子 2024-08-06 06:23:16

显示模式对话框的行为会禁用该对话框的父窗口(示例中的记事本窗口)。 当模式对话框关闭时,父窗口将重新启用。

如果您的程序在重新启用窗口之前终止,则该窗口将永远不会重新启用 - 这取决于显示对话框的线程来重新启用父窗口。 (在您的示例中,它发生在用户单击“确定”或其他操作后的 MessageBox.Show() 内。)

使这项工作有效的唯一方法是拥有第二个进程,其职责是如果创建模式对话框的进程过早终止,事情就会恢复原状,但这很可怕。 而且它仍然不是万无一失的——如果观察者进程也死掉了怎么办?

The act of showing a modal dialog disables the parent window of the dialog (Notepad's window in your example). When the modal dialog is closed, the parent window gets re-enabled.

If your program dies before it re-enables the window, that window will never get re-enabled - it's up to the thread that's showing the dialog to re-enable the parent. (In your example, it happens within MessageBox.Show(), after the user clicks OK or whatever.)

The only way to make this work would be to have a second process whose responsibility it was to put things back as they should be if the process creating the modal dialog dies prematurely, but that's horrible. And it's still not bulletproof - what if the watcher process dies too?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文