C#实现进程间通信

  在C#winform项目中遇到这样一种需求:在shell extension的上下文菜单中,点击一个子菜单,弹出主程序的一个窗体。

  解决这个问题的思路有两个:

  (1)在shell扩展中通过p/invoke调用windows api ——sendmessage,想主程序窗体发送特定信息,同时override主窗体程序的wndProc方法来处理消息。

  (2)注册一个signal,由exporer进程来修改这个signal,主程序来侦听这个signal并作相应的处理。

  由于不清楚windows如何注册signal,我采用的是第一种思路,在codeproject中找到代码,实现功能。

  coder如下:

  common变量:


  /// <summary>

  /// 平台调用帮助类

  /// </summary>

  public class Helpers
     {

    [DllImport("kernel32.dll", SetLastError = true)]
        public static extern IntPtr LocalFree(IntPtr p);

        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern IntPtr LocalAlloc(int flag, int size);

        /// <summary>
        /// The SendMessage API
        /// </summary>
        /// <param name="hWnd">handle to the required window</param>
        /// <param name="Msg">the system/Custom message to send</param>
        /// <param name="wParam">first message parameter</param>
        /// <param name="lParam">second message parameter</param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref CopyDataStruct lParam);

  }

  context menu 中:

  using System.Runtime.InteropServices;

  public struct CopyDataStruct : IDisposable
    {
        public IntPtr dwData;
        public int cbData;
        public IntPtr lpData;

        public void Dispose()
        {
            if (this.lpData != IntPtr.Zero)
            {
                Helpers.LocalFree(this.lpData);
                this.lpData = IntPtr.Zero;
            }
        }
    }

  public static bool SendArgs(IntPtr targetHWnd, string args)
        {
            CopyDataStruct cds = new CopyDataStruct();
            try
            {
                cds.cbData = (args.Length + 1) * 2;
                cds.lpData = Helpers.LocalAlloc(0x40, cds.cbData);
                Marshal.Copy(args.ToCharArray(), 0, cds.lpData, args.Length);
                cds.dwData = (IntPtr)1;
                Helpers.SendMessage(targetHWnd, Helpers.WM_COPYDATA, IntPtr.Zero, ref cds);
            }
            finally
            {
                cds.Dispose();
            }

            return true;
        }

  

    主窗体后台:

  /// <summary>
        /// 消息处理函数
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == Helpers.WM_COPYDATA)
            {
                CopyDataStruct st = (CopyDataStruct)Marshal.PtrToStructure(m.LParam, typeof(CopyDataStruct));
                string strData = Marshal.PtrToStringUni(st.lpData);
                if (strData.Equals(Helpers.SETTING))
                {
                    // 弹出setting窗体
                    preferences_Click(null, null);
                }
            }
            else
            {
                base.WndProc(ref m);
            }
        }

你可能感兴趣的:(C#)