C# 进程之间的通讯
该方法针对同一台服务器上的2个进程之间的通讯,进程A是一个实时采集程序,可能由于某个异常或运行时间过长导致程序卡死,现需要启动另外一个进程B来对
进程A进行定时监控,如果发现A卡死或无故退出,则自动启动进程A。
进程A的代码如下:
public struct COPYDATASTRUCT { public IntPtr dwData; public int cbData; [MarshalAs(UnmanagedType.LPStr)] public string lpData; } [DllImport("User32.dll", EntryPoint = "FindWindow")] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32", EntryPoint = "GetWindowThreadProcessId")] public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int pid); [DllImport("User32.dll", EntryPoint = "SendMessage")] //用SendMessage发送消息必须是针对有窗体显示的进程才可以发送成功 private static extern int SendMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam); //用 PostThreadMessage 可以给无窗体的主线程发送消息 [return: MarshalAs(UnmanagedType.Bool)] [DllImport("user32.dll", SetLastError = true)] public static extern bool PostThreadMessage(int threadId, uint msg, IntPtr wParam, IntPtr lParam); const int WM_COPYDATA = 0x004A; /// <summary> /// 给进程 DCZKStart.exe 发送消息 /// </summary> /// <param name="iflag">消息标记,可以是任意整数值,这个固定0 </param> /// <param name="msg">消息内容</param> private void SendMsgToProcess(int iflag,string msg="") { //利用发送消息方式,给进程 DCZKStart.exe 发送心跳 try { int ihwd = GetDCZKStartProcessHandle(); byte[] sarr = System.Text.Encoding.Default.GetBytes(msg); int len = sarr.Length; COPYDATASTRUCT cds; cds.dwData = (IntPtr)Convert.ToInt16(iflag.ToString());//可以是任意值 cds.cbData = len + 1;//指定lpData内存区域的字节数 cds.lpData = msg;//发送给目标窗口所在进程的数据 SendMessage(ihwd, WM_COPYDATA, 0, ref cds); } catch(Exception ex) { ShowLogInfo(ex.Message, true); } } private int GetDCZKStartProcessHandle() //获取进程 DCZKStart.exe 的进程句柄 { int ihWnd = -1; try { Process p = Process.GetProcessesByName("DCZKStart")[0]; if (p!=null) { IntPtr hwnd = p.MainWindowHandle; //如果窗体最小化,这根据窗体名称来查找 if (hwnd==IntPtr.Zero) { hwnd = FindWindow(null, "DCZKStart_V3"); if (hwnd!=IntPtr.Zero) { ihWnd = (int)hwnd; } } else { ihWnd = (int)hwnd; } } } catch (Exception ex) { ShowLogInfo(ex.Message, true); } return ihWnd; }
其中函数 SendMsgToProcess 就是用来给进程B发送通知消息的,这个消息定时30秒发送一次,以此来告诉进程B它还活着。
这里有一点要注意:就是想要利用SendMessage来发送消息,接收方必须要有窗体,如果窗体隐藏了,则需要通过 FindWindow 来获取窗体句柄。
进程B的代码:
/// <summary> /// 消息接受处理函数 /// </summary> /// <param name="m"></param> protected override void DefWndProc(ref Message m) { try { //以下方法针对有窗体显示的进程才有效 switch (m.Msg) { case WM_COPYDATA: COPYDATASTRUCT cds = new COPYDATASTRUCT(); Type t = cds.GetType(); cds = (COPYDATASTRUCT)m.GetLParam(t); string strResult = cds.dwData.ToString() + ":" + cds.lpData; //根据 strResult 的内容来做出相应的动作
//doSomethings
break; default: base.DefWndProc(ref m); break; } } catch(Exception ex) { ShowLogInfo(ex.Message); } }
posted on 2018-08-21 17:30 lpq22221314 阅读(661) 评论(0) 编辑 收藏 举报