最近公司需要实现一个基于copydata进程间通信的功能。原来一直没有接触过Windows的进程通信,这次正好可以学习一下。
程序是基于Winform的,下面直接上代码。
public class ImportFromDLL { public const int WM_COPYDATA = 0x004A; //启用非托管代码 [StructLayout(LayoutKind.Sequential)] public struct COPYDATASTRUCT { public int dwData; //not used public int cbData; //长度 [MarshalAs(UnmanagedType.LPStr)] public string lpData; } [DllImport("User32.dll")] public static extern int SendMessage( IntPtr hWnd, // handle to destination window int Msg, // message IntPtr wParam, // first message parameter ref COPYDATASTRUCT pcd // second message parameter ); [DllImport("User32.dll", EntryPoint = "FindWindow")] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("Kernel32.dll", EntryPoint = "GetConsoleWindow")] public static extern IntPtr GetConsoleWindow(); }
private void SendMessage() { //声明变量 string filepath = @"D:\GetMsg.exe";//接收消息程序路径 string strText= "hello world!";//发送的消息//遍历系统中运行的进程,获取接收消息的进程 Process[] processes = Process.GetProcesses(); Process process = null; foreach (Process p in processes) { try { //这两个进程的某些属性一旦访问就抛出没有权限的异常 if (p.ProcessName != "System" && p.ProcessName != "Idle") { if (p.ProcessName == "GetMsg") { process = p; break; } } } catch (Exception ex) { MessageBox.Show(ex.Message); } } //如果接收消息的进程未运行,则开启程序 if (process == null) {//启动接收消息程序 process = System.Diagnostics.Process.Start(filepath); Thread.Sleep(100);//等待接收消息的程序完全打开,否则消息不能发送成功。 } //接收端的窗口句柄 IntPtr hwndRecvWindow = process.MainWindowHandle; //自己的进程句柄 IntPtr hwndSendWindow = Process.GetCurrentProcess().Handle; //填充COPYDATA结构 ImportFromDLL.COPYDATASTRUCT copydata = new ImportFromDLL.COPYDATASTRUCT(); copydata.cbData = Encoding.Default.GetBytes(strText).Length; //长度 注意不要用strText.Length; copydata.lpData = strText;//内容 //发送消息 ImportFromDLL.SendMessage(hwndRecvWindow, ImportFromDLL.WM_COPYDATA, hwndSendWindow, ref copydata); return; }
protected override void WndProc(ref Message m) { if (m.Msg == ImportFromDLL.WM_COPYDATA)//根据Message.Msg区分消息类型,ImportFromDLL.WM_COPYDATA为发送方定义的消息类型 { ImportFromDLL.COPYDATASTRUCT copyData = (ImportFromDLL.COPYDATASTRUCT)m.GetLParam(typeof(ImportFromDLL.COPYDATASTRUCT));//获取数据 MessageBox.Show(copyData.lpData); } base.WndProc(ref m); }
1、发送方和接收方均可以用C++、JAVA等实现,此处就不再做讨论。
2、在发送方。如果接收方未开启,就打开接收方,在打开的同时,使用了:
Thread.Sleep(100);//等待接收消息的程序打开,否则消息不能发送成功
让程序等待。若不想让程序等待,由想传递消息给接收方,则可以考虑使用一下开启进程的重载方法:
public static Process Start(string fileName, string arguments); public static Process Start(string fileName, string userName, SecureString password, string domain); public static Process Start(string fileName, string arguments, string userName, SecureString password, string domain);
具体使用说明,可参照API文档。