C#使用SendMessage进行进程间通讯
最近公司有个需求是,拖动文件到桌面图标上,自动打开文件。那么只需在OnStartup事件中通过StartupEventArgs获取文件名然后进行操作即可。操作之后发现当软件已经启动了(单例运行),那么将无法将参数传给业务层。原因是因为跨进程了,那么我们可以通过窗口句柄的方式来进行通讯。
1 public partial class App : Application 2 { 3 private static Mutex AppMutex; 4 public App() 5 { 6 7 } 8 9 protected override void OnStartup(StartupEventArgs e) 10 { 11 //获取启动参数 12 var param = string.Empty; 13 if (e.Args.Length > 0) 14 { 15 param = e.Args[0].ToString(); 16 } 17 18 //WpfApp8 = 你的项目名称 19 AppMutex = new Mutex(true, "WpfApp8", out var createdNew); 20 21 if (!createdNew) 22 { 23 var current = Process.GetCurrentProcess(); 24 25 foreach (var process in Process.GetProcessesByName(current.ProcessName)) 26 { 27 if (process.Id != current.Id) 28 { 29 Win32Helper.SetForegroundWindow(process.MainWindowHandle); 30 Win32Helper.SendMessageString(process.MainWindowHandle, param); 31 break; 32 } 33 } 34 Environment.Exit(0); 35 } 36 else 37 { 38 base.OnStartup(e); 39 } 40 } 41 }
1 public class Win32Helper 2 { 3 [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)] 4 public static extern bool SetForegroundWindow(IntPtr hWnd); 5 6 /// <summary> 7 /// 发送消息 8 /// </summary> 9 /// <param name="hWnd"></param> 10 /// <param name="Msg"></param> 11 /// <param name="wParam"></param> 12 /// <param name="lParam"></param> 13 /// <returns></returns> 14 [DllImport("user32.dll")] 15 public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref COPYDATASTRUCT lParam); 16 17 // 声明常量 18 public const int WM_COPYDATA = 0x004A; 19 20 // 定义 COPYDATASTRUCT 结构 21 [StructLayout(LayoutKind.Sequential)] 22 public struct COPYDATASTRUCT 23 { 24 public IntPtr dwData; 25 public int cbData; 26 public IntPtr lpData; 27 } 28 29 /// <summary> 30 /// 发送字符串消息 31 /// </summary> 32 /// <param name="hWnd"></param> 33 /// <param name="message"></param> 34 public static void SendMessageString(IntPtr hWnd, string message) 35 { 36 if (string.IsNullOrEmpty(message)) return; 37 38 byte[] messageBytes = Encoding.Unicode.GetBytes(message + '\0'); // 添加终止符 39 40 COPYDATASTRUCT cds = new COPYDATASTRUCT(); 41 cds.dwData = IntPtr.Zero; 42 cds.cbData = messageBytes.Length; 43 cds.lpData = Marshal.AllocHGlobal(cds.cbData); 44 Marshal.Copy(messageBytes, 0, cds.lpData, cds.cbData); 45 try 46 { 47 SendMessage(hWnd, WM_COPYDATA, IntPtr.Zero, ref cds); 48 } 49 finally 50 { 51 //释放分配的内存,即使发生异常也不会泄漏资源 52 Marshal.FreeHGlobal(cds.lpData); 53 } 54 } 55 }
1 public partial class MainWindow : Window 2 { 3 public MainWindow() 4 { 5 InitializeComponent(); 6 } 7 8 protected override void OnSourceInitialized(EventArgs e) 9 { 10 base.OnSourceInitialized(e); 11 12 HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource; 13 hwndSource.AddHook(WndProc); 14 } 15 16 private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 17 { 18 if (msg == WM_COPYDATA) 19 { 20 COPYDATASTRUCT cds = (COPYDATASTRUCT)Marshal.PtrToStructure(lParam, typeof(COPYDATASTRUCT)); 21 string receivedMessage = Marshal.PtrToStringUni(cds.lpData); 22 23 Console.WriteLine("收到消息:" + receivedMessage); 24 25 //TODO:业务处理 26 MessageBox.Show(receivedMessage); 27 28 handled = true; 29 } 30 31 return IntPtr.Zero; 32 } 33 }
2024-07-10 14:41:21【出处】:https://www.cnblogs.com/wihalo/p/18293731
=======================================================================================
关注我】。(●'◡'●)
如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的【因为,我的写作热情也离不开您的肯定与支持,感谢您的阅读,我是【Jack_孟】!
本文来自博客园,作者:jack_Meng,转载请注明原文链接:https://www.cnblogs.com/mq0036/p/18294026
【免责声明】本文来自源于网络,如涉及版权或侵权问题,请及时联系我们,我们将第一时间删除或更改!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
2023-07-10 介绍Linux shell脚本学习 -- 系列文章
2023-07-10 JS中的浏览器对象
2023-07-10 ASP.NET Core 6框架揭秘实例演示[42]:检查应用程序的健康状况
2023-07-10 尽可能避免在静态构造函数中初始化静态字段?
2020-07-10 树莓派安装MySQL数据库
2014-07-10 时间管理