簡體   English   中英

如何從其 Win32 句柄中獲取 System.Windows.Form 實例?

[英]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_) 消息,但很難獲取數據。

選項

  1. 在臨時文件中使用低級別的東西。

  2. 使用遠程處理 (WCF)

嘗試以下

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

編輯

重新閱讀您的問題並意識到您正在查看另一個進程中的句柄。 無法將另一個進程中的句柄轉換為當前進程中的 Form 實例。 我的解決方案僅適用於同一進程中的句柄。

獲得 Form 實例的唯一方法是使用 Remoting。 但這需要兩個過程的合作,而這似乎不是您想要的。

您確實在嘗試實現 singleton 應用程序。 網上有幾個例子(對不起,我自己沒有真正嘗試過),例如

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

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

你不能直接調用另一個進程中的代碼,你需要使用某種形式的進程間通信

如果您僅在同一台計算機上由同一用戶啟動的進程之間進行通信,您可以使用 window 消息(使用 WinAPI PostMessage 並覆蓋 WndProc),否則我認為遠程處理是最容易在 Z2D50972FECCD37612895455 中使用的

我使用 nobugz 指向的線程中描述的 Microsoft.VisualBasic.dll 庫。 是的,您可以在 C# 中使用它。 您只需覆蓋 OnStartupNextInstance 並以最適合您的方式將命令行傳遞到您的程序中。

這比手動處理線程要容易得多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM