[英]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.