C#桌面应用与Flutter桌面应用能否离线互传字符串参数?
无网络环境下C#与Flutter桌面应用的本地通信方案
下面是几种无需网络的本地进程间通信(IPC)方案,直接适配C#和Flutter桌面应用,可实现字符串参数的互相传递:
1. 命名管道(Named Pipes)
这是Windows平台原生的IPC机制,跨语言兼容性好,C#和Flutter都能轻松实现。
C# 端实现(服务器/客户端)
using System.IO.Pipes; using System.Text; // 作为服务器监听管道 var pipeServer = new NamedPipeServerStream("FlutterCSharpIPC", PipeDirection.InOut); pipeServer.WaitForConnection(); // 读取Flutter发来的字符串 byte[] buffer = new byte[1024]; int bytesRead = pipeServer.Read(buffer, 0, buffer.Length); string receivedMsg = Encoding.UTF8.GetString(buffer, 0, bytesRead); Console.WriteLine($"收到Flutter消息: {receivedMsg}"); // 发送响应给Flutter string response = "C#已接收消息,这是响应"; byte[] responseBytes = Encoding.UTF8.GetBytes(response); pipeServer.Write(responseBytes, 0, responseBytes.Length); pipeServer.Close();
Flutter 端实现(客户端)
可以用named_pipes第三方包简化开发:
import 'package:named_pipes/named_pipes.dart'; void main() async { final pipe = NamedPipeClient('FlutterCSharpIPC'); await pipe.connect(); // 发送字符串给C# await pipe.writeString("来自Flutter的测试消息"); // 读取C#的响应 String response = await pipe.readString(); print("收到C#响应: $response"); await pipe.disconnect(); }
注意:管道名称必须完全一致,Windows下要注意权限设置;如果是Linux/macOS平台,可以改用Unix域套接字实现类似逻辑。
2. 共享内存(Shared Memory)
适合高频、低延迟的消息传递,通过一块共享的内存区域实现数据交换。
C# 端实现
using System.IO.MemoryMappedFiles; using System.Text; // 创建或打开共享内存区域 using var mmf = MemoryMappedFile.CreateOrOpen("CSharpFlutterSharedMem", 1024); using var stream = mmf.CreateViewStream(); using var writer = new BinaryWriter(stream); // 写入字符串到共享内存 writer.Write("来自C#的共享内存消息"); writer.Flush(); // 读取Flutter写入的内容(可选) stream.Position = 0; using var reader = new BinaryReader(stream); string receivedMsg = reader.ReadString(); Console.WriteLine($"共享内存收到Flutter消息: {receivedMsg}");
Flutter 端实现
使用shared_memory包操作共享内存:
import 'dart:convert'; import 'package:shared_memory/shared_memory.dart'; void main() async { // 打开共享内存 int shmId = await SharedMemory.createOrOpen("CSharpFlutterSharedMem", 1024); // 读取C#写入的字符串 Uint8List buffer = await SharedMemory.read(shmId, 0, 1024); String receivedMsg = utf8.decode(buffer).trim(); print("共享内存收到C#消息: $receivedMsg"); // 写入消息到共享内存 Uint8List sendBuffer = utf8.encode("来自Flutter的共享内存消息"); await SharedMemory.write(shmId, 0, sendBuffer); // 关闭共享内存 await SharedMemory.close(shmId); }
注意:共享内存没有内置同步机制,需要额外加互斥锁(比如C#用Mutex,Flutter用win32插件调用系统Mutex)避免读写冲突。
3. 本地文件监听(File Watcher)
适合低频率、简单的消息传递逻辑,通过监听指定本地文件的内容变化实现通信。
C# 端实现
using System.IO; using System.Text; // 监听消息文件变化 var watcher = new FileSystemWatcher(@"C:\Temp", "IPC_Message.txt"); watcher.Changed += (sender, e) => { string content = File.ReadAllText(e.FullName, Encoding.UTF8); Console.WriteLine($"收到文件消息: {content}"); // 写入响应到指定文件 File.WriteAllText(@"C:\Temp\IPC_Response.txt", "C#已接收消息"); }; watcher.EnableRaisingEvents = true; // 发送消息到文件 File.WriteAllText(@"C:\Temp\IPC_Message.txt", "来自C#的文件消息");
Flutter 端实现
用path_provider获取本地目录,file_watcher监听文件变化:
import 'dart:io'; import 'package:path_provider/path_provider.dart'; import 'package:file_watcher/file_watcher.dart'; void main() async { Directory tempDir = await getTemporaryDirectory(); String msgPath = "${tempDir.path}/IPC_Message.txt"; String respPath = "${tempDir.path}/IPC_Response.txt"; // 监听消息文件 final watcher = FileWatcher(msgPath); watcher.events.listen((event) { if (event.type == ChangeType.modified) { String content = File(msgPath).readAsStringSync(); print("收到文件消息: $content"); File(respPath).writeAsStringSync("Flutter已接收消息"); } }); // 发送消息到文件 File(msgPath).writeAsStringSync("来自Flutter的文件消息"); }
注意:要处理文件读写的并发问题,避免文件被占用,适合逻辑简单、对实时性要求不高的场景。
4. Windows消息(仅限Windows平台)
如果你的两个应用都运行在Windows上,用Windows消息机制是最轻便的方案,直接通过窗口句柄传递字符串。
C# 端实现
using System; using System.Runtime.InteropServices; public static class Win32API { [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr FindWindow(string className, string windowName); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern int SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); } void SendMessageToFlutter() { // 通过窗口标题查找Flutter应用窗口句柄 IntPtr flutterWindow = Win32API.FindWindow(null, "Flutter App"); if (flutterWindow != IntPtr.Zero) { // 自定义消息ID(WM_USER + 0x100,避免系统消息冲突) const uint WM_CUSTOM_MSG = 0x0400 + 0x100; // 将字符串转为指针传递 string msg = "来自C#的Windows消息"; IntPtr msgPtr = Marshal.StringToHGlobalAuto(msg); Win32API.SendMessage(flutterWindow, WM_CUSTOM_MSG, IntPtr.Zero, msgPtr); Marshal.FreeHGlobal(msgPtr); } }
Flutter 端实现
用win32插件监听窗口消息:
import 'package:win32/win32.dart'; void main() { // 获取当前Flutter窗口句柄 final hWnd = GetForegroundWindow(); // 保存原有窗口过程,用于回调转发 WNDPROC? oldProc; int windowProc(int hWnd, uint uMsg, int wParam, int lParam) { const WM_CUSTOM_MSG = 0x0400 + 0x100; if (uMsg == WM_CUSTOM_MSG) { // 解析收到的字符串 String msg = Marshal.PtrToStringAuto(lParam); print("收到Windows消息: $msg"); // 可选:发送响应给C#(需要提前获取C#窗口句柄) // SendMessage(cSharpWndHandle, WM_CUSTOM_MSG, 0, Marshal.StringToHGlobalAuto("Flutter已收到").address); } // 调用原有窗口过程处理其他消息 return CallWindowProc(oldProc!, hWnd, uMsg, wParam, lParam); } // 设置自定义窗口过程 oldProc = SetWindowLongPtr(hWnd, GWLP_WNDPROC, Pointer.fromFunction<IntPtr Function(IntPtr, UInt32, IntPtr, IntPtr)>(windowProc)); }
注意:自定义消息ID要两端保持一致,窗口句柄可以通过标题、进程ID等方式获取。
方案选择建议
- 跨平台需求:优先选命名管道(Windows)/Unix域套接字(Linux/macOS),或共享内存
- Windows专属场景:Windows消息最轻便高效
- 简单低频率通信:本地文件监听成本最低
内容的提问来源于stack exchange,提问作者Pedro Lincolm
相关产品推荐
相关产品推荐

