另一个进程上的模态消息框 句柄可能会锁定目标进程
如果我将 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
显示模式对话框的行为会禁用该对话框的父窗口(示例中的记事本窗口)。 当模式对话框关闭时,父窗口将重新启用。
如果您的程序在重新启用窗口之前终止,则该窗口将永远不会重新启用 - 这取决于显示对话框的线程来重新启用父窗口。 (在您的示例中,它发生在用户单击“确定”或其他操作后的
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?