IM项目刚开始,由于IM客户端要与VMEETING通信,所以就做了技术调研,跨进程通信,我们使用的是windows api的findwindow找到窗口,然后用send message通信。(此方案只适用于接收端有window的场景)
接收端代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; using System.IO; namespace ProcessServer { public partial class FrmProcessServer : Form { public FrmProcessServer() { InitializeComponent(); } #region const data const int WM_COPYDATA = 0x004A; public struct COPYDATASTRUCT { public IntPtr dwData; public int cbData; [MarshalAs(UnmanagedType.LPStr)] public string lpData; } #endregion [DllImport("user32")] public static extern bool ChangeWindowMessageFilter(uint msg, int flags); #region windows api functions protected override void DefWndProc(ref System.Windows.Forms.Message m) { switch (m.Msg) { case WM_COPYDATA: COPYDATASTRUCT mystr = new COPYDATASTRUCT(); Type mytype = mystr.GetType(); mystr = (COPYDATASTRUCT)m.GetLParam(mytype); File.WriteAllText("D:/processText.txt", "recieved:" + mystr.lpData); lstMessageList.Items.Add(mystr.lpData); break; default: base.DefWndProc(ref m); break; } } #endregion private void btnListen_Click(object sender, EventArgs e) { } private void FrmProcessServer_Load(object sender, EventArgs e) { ChangeWindowMessageFilter(WM_COPYDATA, 1); } } }
发送端代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; namespace ProcessClient { public partial class FrmClientSender : Form { public FrmClientSender() { InitializeComponent(); } //define const datas const int WM_COPYDATA = 0x004A; public enum ChangeWindowMessageFilterFlags : uint { Add = 1, Remove = 2 }; public struct COPYDATASTRUCT { public IntPtr dwData; public int cbData; [MarshalAs(UnmanagedType.LPStr)] public string lpData; } #region Dll Import [DllImport("User32.dll", EntryPoint = "FindWindow")] private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll", EntryPoint = "FindWindowEx")] private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); [DllImport("User32.dll", EntryPoint = "SendMessage")] private static extern int SendMessage( int hWnd, // handle to destination window int Msg, // message int wParam, // first message parameter ref COPYDATASTRUCT lParam // second message parameter ); [DllImport("user32")] public static extern bool PostMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); [DllImport("user32")] public static extern uint RegisterWindowMessage(string msg); [DllImport("user32")] public static extern bool ChangeWindowMessageFilter(uint msg, ChangeWindowMessageFilterFlags flags); #endregion #region public methods private static void SendMessageToProcess(string processWindowName, string message) { IntPtr WINDOWHANDLER = FindWindow(null, processWindowName); if ((int)WINDOWHANDLER == 0) { MessageBox.Show("reciver not found!"); } else { //send message byte[] sarr = System.Text.Encoding.Default.GetBytes(message); int len = sarr.Length; COPYDATASTRUCT cds; cds.dwData = (IntPtr)100; cds.lpData = message; cds.cbData = len + 1; SendMessage((int)WINDOWHANDLER, WM_COPYDATA, 0, ref cds); } } #endregion private void FrmClientSender_Load(object sender, EventArgs e) { } private void btnSend_Click(object sender, EventArgs e) { SendMessageToProcess(txtReciver.Text, txtMessage.Text); } } }
注:vista或win7中引入了uac机制,当以管理员身份运行时,仅仅调用send message这个api给接收端发是收不到的,接收端需要加上这句: ChangeWindowMessageFilter(WM_COPYDATA, 1) //告诉操作系统那条消息不要被过滤掉。