You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

同一机器上不同WPF应用如何通信?如何激活并发送文本消息?

嘿,针对你问的两个WPF应用通信相关问题,我整理了几种实用的实现方案,都是在同一台机器上完全可行的:

问题1:同一台机器上两个WPF应用的相互通信

这里有三种常用且可靠的实现方式,你可以根据场景选择:

方法1:使用.NET命名管道(Named Pipes)

这是本地进程通信(IPC)里最轻便的方案之一,.NET原生支持,不需要额外依赖。

服务端应用(接收消息的WPF应用)

在后台线程启动监听,避免阻塞UI:

using System.IO.Pipes;
using System.Threading.Tasks;

private async void StartPipeServer()
{
    while (true)
    {
        using (var pipeServer = new NamedPipeServerStream("WpfAppPipe", PipeDirection.InOut))
        {
            await pipeServer.WaitForConnectionAsync();
            using (var reader = new StreamReader(pipeServer))
            using (var writer = new StreamWriter(pipeServer))
            {
                string message = await reader.ReadLineAsync();
                // 在UI线程更新内容
                Dispatcher.Invoke(() => MessageBox.Show($"收到消息:{message}"));
                // 可选:回复消息
                await writer.WriteLineAsync("消息已收到");
                await writer.FlushAsync();
            }
        }
    }
}

客户端应用(发送消息的WPF应用)

连接到管道并发送消息:

using System.IO.Pipes;
using System.Threading.Tasks;

private async void SendMessageToServer()
{
    using (var pipeClient = new NamedPipeClientStream(".", "WpfAppPipe", PipeDirection.InOut))
    {
        await pipeClient.ConnectAsync(5000); // 5秒超时
        using (var writer = new StreamWriter(pipeClient))
        using (var reader = new StreamReader(pipeClient))
        {
            await writer.WriteLineAsync("来自客户端的测试消息");
            await writer.FlushAsync();
            // 可选:接收回复
            string response = await reader.ReadLineAsync();
            MessageBox.Show($"服务端回复:{response}");
        }
    }
}

方法2:使用WCF(Windows Communication Foundation)

如果需要更复杂的通信模式(比如双向调用、回调),WCF是不错的选择,本地通信推荐用NetNamedPipeBinding。

定义服务契约

在两个应用都能访问的类库(或各自复制代码)中定义:

using System.ServiceModel;

[ServiceContract]
public interface IAppCommunication
{
    [OperationContract]
    string SendMessage(string message);
}

服务端实现与启动

在接收端WPF应用中:

using System.ServiceModel;

private ServiceHost _serviceHost;

private void StartWcfService()
{
    var binding = new NetNamedPipeBinding();
    var address = new EndpointAddress("net.pipe://localhost/WpfAppComm");
    _serviceHost = new ServiceHost(typeof(AppCommunicationService), address);
    _serviceHost.AddServiceEndpoint(typeof(IAppCommunication), binding, address);
    _serviceHost.Open();
}

public class AppCommunicationService : IAppCommunication
{
    public string SendMessage(string message)
    {
        // 回到UI线程处理消息
        Application.Current.Dispatcher.Invoke(() => 
            MessageBox.Show($"收到WCF消息:{message}"));
        return "WCF消息已处理";
    }
}

客户端调用

在发送端WPF应用中:

using System.ServiceModel;

private async void CallWcfService()
{
    var binding = new NetNamedPipeBinding();
    var address = new EndpointAddress("net.pipe://localhost/WpfAppComm");
    var factory = new ChannelFactory<IAppCommunication>(binding, address);
    var channel = factory.CreateChannel();
    
    string response = channel.SendMessage("WCF测试消息");
    MessageBox.Show($"WCF服务端回复:{response}");
    
    ((IClientChannel)channel).Close();
    factory.Close();
}

方法3:使用Windows消息(Win32 API)

通过Win32的SendMessage或PostMessage发送自定义消息,适合轻量的消息传递,需要处理窗口句柄和消息注册。

第一步:注册自定义消息ID

在两个应用中都定义同一个消息ID(确保唯一):

using System.Runtime.InteropServices;

public static class Win32Messages
{
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern uint RegisterWindowMessage(string lpString);
    
    public static readonly uint WM_APP_MESSAGE = RegisterWindowMessage("WPF_APP_COMM_MESSAGE");
}

服务端(接收消息)

在WPF窗口中重写WndProc处理消息:

protected override void OnSourceInitialized(EventArgs e)
{
    base.OnSourceInitialized(e);
    HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
    source.AddHook(WndProc);
}

private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    if ((uint)msg == Win32Messages.WM_APP_MESSAGE)
    {
        string message = Marshal.PtrToStringUni(lParam);
        MessageBox.Show($"收到Windows消息:{message}");
        handled = true;
    }
    return IntPtr.Zero;
}

客户端(发送消息)

先找到目标窗口的句柄,然后发送消息:

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

private void SendWin32Message()
{
    // 根据窗口标题查找目标WPF应用的窗口句柄
    IntPtr targetWindowHandle = FindWindow(null, "目标应用窗口标题");
    if (targetWindowHandle != IntPtr.Zero)
    {
        string message = "来自Win32的消息";
        IntPtr messagePtr = Marshal.StringToHGlobalUni(message);
        SendMessage(targetWindowHandle, Win32Messages.WM_APP_MESSAGE, IntPtr.Zero, messagePtr);
        Marshal.FreeHGlobal(messagePtr);
    }
    else
    {
        MessageBox.Show("未找到目标应用窗口");
    }
}

问题2:激活正在运行的WPF应用并发送文本消息

这个需求需要分两步:找到并激活目标应用窗口,然后发送文本消息,结合上面的方案可以轻松实现。

步骤1:查找并激活目标WPF应用

用Process类找到目标进程,再获取主窗口句柄并激活:

using System.Diagnostics;
using System.Runtime.InteropServices;

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);

private bool ActivateTargetApp(string processName)
{
    Process[] processes = Process.GetProcessesByName(processName);
    if (processes.Length > 0)
    {
        Process targetProcess = processes[0];
        if (targetProcess.MainWindowHandle != IntPtr.Zero)
        {
            SetForegroundWindow(targetProcess.MainWindowHandle);
            return true;
        }
        // 如果主窗口句柄为空,可能是WPF窗口还没初始化,试试遍历所有窗口
        // 这里可以结合FindWindow或者EnumWindows来查找具体窗口
    }
    MessageBox.Show("目标应用未运行");
    return false;
}

步骤2:发送文本消息到激活的应用

激活后,直接用上面提到的命名管道、WCF或Windows消息发送文本即可。比如结合Windows消息的完整流程:

private void ActivateAndSendMessage()
{
    if (ActivateTargetApp("TargetWpfApp")) // 替换成目标应用的进程名(不带.exe)
    {
        IntPtr targetWindowHandle = FindWindow(null, "目标应用窗口标题");
        if (targetWindowHandle != IntPtr.Zero)
        {
            string textToSend = "激活后发送的文本消息";
            IntPtr textPtr = Marshal.StringToHGlobalUni(textToSend);
            SendMessage(targetWindowHandle, Win32Messages.WM_APP_MESSAGE, IntPtr.Zero, textPtr);
            Marshal.FreeHGlobal(textPtr);
        }
    }
}

额外提示

  • 如果用命名管道或WCF,激活后直接调用发送逻辑即可,不需要窗口句柄,更可靠。
  • WPF窗口的句柄可以通过WindowInteropHelper获取:new WindowInteropHelper(this).Handle,方便在服务端获取自己的句柄用于调试。

内容的提问来源于stack exchange,提问作者Santhosh Sebastian Mattathil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:14:49