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编辑  收藏  举报

导航