同一机器上不同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
相关产品推荐
相关产品推荐

