如何从Win32句柄获取System.Windows.Form实例?

以下代码实现了一个简单的单例,确保只能运行我的应用程序的一个实例。 但是,如果启动了另一个实例,我需要能够获取该实例的命令行参数,将它们传递给初始实例,然后终止第二个实例。

当我试图获取应用程序的第一个实例时,会出现此问题。 一旦我找到该实例的主窗体的句柄,我将它传递给Control.FromHandle()方法,期望得到一个MainForm 。 相反,返回值始终为null 。 ( Control.FromChildHandle()给出相同的结果。)

因此,我的问题很简单:我做错了什么? 这在.NET中甚至可能吗?

 public class MainForm : Form { [DllImport("user32")] extern static int ShowWindowAsync(IntPtr hWnd, int nCmdShow); [DllImport("user32")] extern static bool SetForegroundWindow(IntPtr hWnd); private Mutex singletonMutex; private void MainForm_Load(object sender, EventArgs e) { bool wasCreated; singletonMutex = new Mutex(false, Application.ProductName + "Mutex", out wasCreated); // returns false for every instance except the first if (!wasCreated) { Process thisProcess = Process.GetCurrentProcess(); Process[] peerProcesses = Process.GetProcessesByName(thisProcess.ProcessName.Replace(".vshost", string.Empty)); foreach (Process currentProcess in peerProcesses) { if (currentProcess.Handle != thisProcess.Handle) { ShowWindowAsync(currentProcess.MainWindowHandle, 1); // SW_NORMAL SetForegroundWindow(currentProcess.MainWindowHandle); // always returns null !!! MainForm runningForm = (MainForm) Control.FromHandle(currentProcess.MainWindowHandle); if (runningForm != null) { runningForm.Arguments = this.Arguments; runningForm.ProcessArguments(); } break; } } Application.Exit(); return; } } 

.NET框架很好地支持单实例应用程序。 请查看此主题以获取您所需要的示例。

Control.FromHandle无法正常工作,因为您正在寻找的控件位于另一个进程中(因此位于另一个应用程序域中)。

您已经拥有WindowHandle,但它的使用仅限于Win32 API。 WinForms什么都不会起作用。

您可以发送(WM_)消息,但很难获取数据。

选项

  1. 使用低级别的临时文件。

  2. 使用远程处理(WCF)

您真的在尝试实现单例应用程序。 互联网上有一些例子(对不起,没有真正尝试过自己),例如

http://www.codeproject.com/KB/cs/SingletonApplication.aspx

http://www.nathanm.com/csharp-wpf-singleton-application/

请尝试以下方法

 var form = (Form)(Control.FromHandle(myHandle)); 

编辑

重新阅读你的问题,并意识到你正在寻找另一个过程中的句柄。 无法将另一个进程中的句柄转换为当前进程中的Form实例。 我的解决方案仅适用于同一进程中的句柄。

获取Form实例的唯一方法是使用Remoting。 但这需要两个过程的合作,这似乎不是你想要的。

您无法直接在另一个进程中调用代码,您需要使用某种forms的进程间通信

如果您只是在同一台计算机上由同一用户启动的进程之间进行通信,则可以使用窗口消息(使用WinAPI PostMessage并覆盖WndProc),否则我认为远程处理在.net中最容易使用

我使用nobugz指向的线程中描述的Microsoft.VisualBasic.dll库。 是的,你可以在C#中使用它。 您只需覆盖OnStartupNextInstance并以最适合您的方式将命令行传递到您的程序中。

这比手动处理线程容易得多。