切换到同一应用程序的其他实例

如果发生某个事件,我希望我的c#winform应用程序切换到另一个正在运行的实例。

例如,如果我有一个只有一个按钮的应用程序,并且此时正在运行三个实例。 现在,如果我

  1. 在第一个实例中按下按钮,焦点到第二个实例
  2. 在第二个实例中按下按钮,焦点到第三个实例
  3. 在第三个实例中按下按钮,焦点到第一个实例

我怎么做?

如果你知道其他实例的句柄,你应该只调用Windows API: SetForegroundWindow

[DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindow(string lpClassName, string lpWindowName); 

您可以使用FindWindow API调用来获取其他实例的句柄,例如:

  public static int FindWindow(string windowName) { int hWnd = FindWindow(null, windowName); return hWnd; } 

您可以在SO中搜索这些api调用以获取更多示例,例如找到这个:

如何聚焦外窗?

SetForegroundWindow是一个很好的解决方案。 另一种方法是使用命名Semaphores将信号发送到其他应用程序。

最后,您可以查找Inter-Process Communication (IPC)解决方案,该解决方案允许您在进程之间发送消息。

我写了一个简单的.Net XDMessaging库,这使得这很容易。 使用它,您可以将指令从一个应用程序发送到另一个应用程序,在最新版本中甚至可以传递已上传的对象。 它是一种使用通道概念的多播实现。

应用1:

 IXDBroadcast broadcast = XDBroadcast.CreateBroadcast( XDTransportMode.WindowsMessaging); broadcast.SendToChannel("commands", "focus"); 

应用2:

 IXDListener listener = XDListener.CreateListener( XDTransportMode.WindowsMessaging); listener.MessageReceived+=XDMessageHandler(listener_MessageReceived); listener.RegisterChannel("commands"); // process the message private void listener_MessageReceived(object sender, XDMessageEventArgs e) { // e.DataGram.Message is the message // e.DataGram.Channel is the channel name switch(e.DataGram.Message) { case "focus": // check requires invoke this.focus(); break; case "close" this.close(); break; } }