[英]How do I get a System.Windows.Form instance from its Win32 handle?
下面的代码实现了一个简单的 singleton,它确保我的应用程序只有一个实例可以运行。 但是,如果启动另一个实例,我需要能够获取该实例的命令行 arguments,将它们传递给初始实例,然后终止第二个实例。
当我试图获取应用程序的第一个实例时,问题就出现了。 一旦我找到了该实例的主窗体的句柄,我将它传递给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_) 消息,但很难获取数据。
选项
在临时文件中使用低级别的东西。
使用远程处理 (WCF)
尝试以下
var form = (Form)(Control.FromHandle(myHandle));
编辑
重新阅读您的问题并意识到您正在查看另一个进程中的句柄。 无法将另一个进程中的句柄转换为当前进程中的 Form 实例。 我的解决方案仅适用于同一进程中的句柄。
获得 Form 实例的唯一方法是使用 Remoting。 但这需要两个过程的合作,而这似乎不是您想要的。
您确实在尝试实现 singleton 应用程序。 网上有几个例子(对不起,我自己没有真正尝试过),例如
你不能直接调用另一个进程中的代码,你需要使用某种形式的进程间通信
如果您仅在同一台计算机上由同一用户启动的进程之间进行通信,您可以使用 window 消息(使用 WinAPI PostMessage 并覆盖 WndProc),否则我认为远程处理是最容易在 Z2D50972FECCD37612895455 中使用的
我使用 nobugz 指向的线程中描述的 Microsoft.VisualBasic.dll 库。 是的,您可以在 C# 中使用它。 您只需覆盖 OnStartupNextInstance 并以最适合您的方式将命令行传递到您的程序中。
这比手动处理线程要容易得多。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.