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

本文关键字:其他 实例 应用程序 | 更新日期: 2023-09-27 18:07:59

我希望我的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库,使这非常容易。使用它,您可以将指令从一个应用程序发送到另一个应用程序,在最新版本中甚至可以传递序列化的对象。这是一个使用信道概念的多播实现。

App1:

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

App2:

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;
    }
}