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

C# 如何从其Win32句柄获取System.Windows.Form实例?,c#,winforms,winapi,interop,ipc,C#,Winforms,Winapi,Interop,Ipc,下面的代码实现了一个简单的单例,它确保只能运行我的应用程序的一个实例。但是,如果启动了另一个实例,我需要能够获取该实例的命令行参数,将它们传递给初始实例,然后终止第二个实例 当我试图获取应用程序的第一个实例时,问题就出现了。找到该实例主窗体的句柄后,我将其传递给控件。FromHandle()方法,希望返回MainForm。相反,返回值总是null。(Control.FromChildHandle()给出了相同的结果。) 因此,我的问题很简单:我做错了什么?这在.NET中可能吗 public cl

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

当我试图获取应用程序的第一个实例时,问题就出现了。找到该实例主窗体的句柄后,我将其传递给
控件。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;
  }
}
试试下面的方法

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

重新阅读您的问题,并意识到您正在查看另一个进程中的句柄。无法将另一进程中的句柄转换为当前进程中的窗体实例。我的解决方案只适用于同一进程中的句柄


获取表单实例的唯一方法是使用远程处理。但这将需要两个过程的合作,而这似乎不是你想要的

Control.FromHandle不起作用,因为您要查找的控件位于另一个进程中(因此位于另一个appdomain中)

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

您可以发送(WM_u3;)消息,但很难获得数据

选择权

  • 用低层次的语言来表达 临时文件

  • 使用远程处理(WCF)


  • 您实际上是在尝试实现一个单例应用程序。互联网上有几个例子(对不起,我自己还没有试过),例如


    您不能直接调用另一个进程中的代码,您需要使用某种形式的进程间通信


    如果您仅在同一台计算机上由同一用户启动的进程之间进行通信,则可以使用窗口消息(使用WinAPI PostMessage并覆盖WndProc),否则我认为远程处理是.net中最容易使用的方法。单实例应用程序受到.net framework的良好支持。检查是否有一个完全符合您需要的示例。

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


    这比手动处理线程要简单得多。

    谢谢-我完全忘记了WindowsFormsApplicationBase类。System.Windows.Forms命名空间中没有包含这样一个有用的类,这对我来说似乎很奇怪,但很好。