用SendMessage用于进程间通信使用自定义消息,String含在Struct里,接收方却得到null?
在网上找了一下可以用“结构体封装string字段”,但是我试过,接收方可以收到消息,得到的String却是null,不知道为什么?如果要传其它数据类型,如byte,int之类的应该怎么传送?
发送方: public const int WM_USER = 0x500;
        public const int RF_CMD = WM_USER + 13;
        public struct RFDataStruct
        {
            public int rfLength;
            public string rfData;
        }        byte rfCmd = 0;        [DllImport("user32.dll")]
        public static extern bool SendMessage(IntPtr hWnd, int Msg, int wParam, ref RFDataStruct lparam);        private void buttonSend_Click(object sender, EventArgs e)
        {
            Process[] vProcesses = Process.GetProcessesByName("PorcessReceiveUserDefinedMessageDemo"); // 查询目标进程
            if (vProcesses.Length <= 0)
                vProcesses = Process.GetProcessesByName("PorcessReceiveUserDefinedMessageDemo.vshost");  //Debug调试进程
            if (vProcesses.Length <= 0)
            {
                MessageBox.Show("目标进程没有找到!");
                return;
            }            if (comboBoxRF.Text == comboBoxRF.Items[0].ToString()) rfCmd = 0;
            else if (comboBoxRF.Text == comboBoxRF.Items[1].ToString()) rfCmd = 1;
            else if (comboBoxRF.Text == comboBoxRF.Items[2].ToString()) rfCmd = 2;  //SelectedText不行,始终为空
            else rfCmd = 3;
            string rfCmdString = rfCmd.ToString("X2");            RFDataStruct rfMessage = new RFDataStruct();
            rfMessage.rfData = rfCmdString;
            rfMessage.rfLength = rfMessage.rfData.Length;
            foreach (Process vProcess in vProcesses)
            {
                bool returnValue3 = SendMessage(vProcess.MainWindowHandle, RF_CMD, 1, ref rfMessage);
            }
        }接收方:  public const int WM_USER = 0x500;
        public const int RF_CMD = WM_USER + 13;        public struct RFDataStruct
        {
            public string rfData;
            public int rfLength;
        }        protected override void DefWndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case RF_CMD:
                    RFDataStruct rfDataStruct = new RFDataStruct();
                    Type type = rfDataStruct.GetType();
                    rfDataStruct = (RFDataStruct)m.GetLParam(type);
                    string rfCmd = rfDataStruct.rfData;
                    //string rfCmd = Marshal.PtrToStringBSTR(m.LParam);
                    textBox1.Text = rfCmd;
                    break;
                default:
                    base.DefWndProc(ref m);
                    break;
            }
            //base.WndProc(ref m);
        }rfCmd为null,rfData为0,而且发现用SendMessage有时会出现异常“外部组件发生异常”。
以下是我从网上找到的例子,唯一不同的是它是在同一个进程的两个窗口之间传递,在接收方窗体里没有定义结构体,直接用的发送窗体的结构体,它的是可以收到的。
发送窗体  //自定义的消息
        public const int USER = 0x500;
        public const int MYMESSAGE = USER + 1;        public Form2()
        {
            InitializeComponent();
        }        IntPtr HD;        public Form2(IntPtr hd)
        {
            InitializeComponent();
            HD = hd;
        }        private void button1_Click(object sender, EventArgs e)
        {
            IntPtr ptr = FindWindow(null, "Form1");//获取接收消息的窗体句柄
            //消息构建
            My_lParam m = new My_lParam();
            m.s = textBox1.Text;
            m.i = m.s.Length;
            SendMessage(ptr, MYMESSAGE, 1, ref m);//发送消息
        }        public  struct My_lParam
        {
            public int i;
            public string s;
        }        //消息发送API
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        private static extern int SendMessage(
        IntPtr hWnd,        // 信息发往的窗口的句柄
        int Msg,            // 消息ID
        int wParam,         // 参数1
        ref My_lParam lParam
        );        [DllImport("User32.dll", EntryPoint = "FindWindow")]
        private extern static IntPtr FindWindow(string lpClassName, string lpWindowName); 接收窗体:public const int USER = 0x500;
        public const int MYMESSAGE = USER + 1;
        public Form1()
        {
            InitializeComponent();
        }        private void button1_Click(object sender, EventArgs e)
        {
            Form2 f = new Form2(this.Handle);
            f.Show();
        }        ///重写窗体的消息处理函数DefWndProc,从中加入自己定义消息 MYMESSAGE 的检测的处理入口
        protected override void DefWndProc(ref Message m)
        {
            switch (m.Msg)
            {
                //接收自定义消息MYMESSAGE,并显示其参数
                case MYMESSAGE:                    Form2.My_lParam ml = new Form2.My_lParam();
                    Type t = ml.GetType();
                    ml = (Form2.My_lParam)m.GetLParam(t);
                    label1.Text = ml.s;                    //SendCustomMessage.SENDDATASTRUCT myData = new SendCustomMessage.SENDDATASTRUCT();//这是创建自定义信息的结构
                    //Type mytype = myData.GetType();
                    //myData = (SendCustomMessage.SENDDATASTRUCT)m.GetLParam(mytype);//这里获取的就是作为LParam参数发送来的信息的结构
                    //textBox1.Text = myData.lpData; //显示收到的自定义信息
                    break;
                default:
                    base.DefWndProc(ref m);
                    break;
            }        }SendMessage  自定义消息

解决方案 »

  1.   

    try
    发送intptr
    Marshal.stringtoptrauto
      

  2.   

    在两个进程间传结构,MYMESSAGE = USER + 1是一定不可以的。
    原因是,两个进程的内存空间是独立的。在某个进程有效的指针,对另外一个进程而言,就是垃圾。解决:
    方法一、建议不用Windows消息(局限会越来越大),用Socket,Named Pipe,WCF等等。
    方法二、用WM_COPYDATA,系统会帮你拷贝数据到另外一个进程。
      

  3.   

    没有Marshal.stringtoptrauto,发送方用Marshal.StringToHGlobalAuto,接收方用Marshal.PtrToStringAuto,收到的是乱码。
    其实我之前也试过发送方用Marshal.StringToHGlobalAnsi,接收方用Marshal.PtrToStringAnsi,收到的都是乱码。
      

  4.   

    不好意思,你说的是传结构。
    如果想用自定义消息传送String,或者是byte整型数据,该怎么传送呢?
    因为对方已经用自定义消息收了,如果要改其它方式,对方也要改。
      

  5.   

    接收方可以收到消息,得到的String却是null。只要看上面两段的。
      

  6.   

    正如楼上两位所说,用自定义消息在两进程间传结构是不能传的。
    你知道如何在两进程间用自定义消息在两进程间传递byte等之类的整型。
      

  7.   

    各位,我用最简单的方式发送出去了,直接重载SendMessage为要所发的整型,接收方强转,本来以为不会这么简单的,想不到这样可行。
    发送方:  public const int WM_USER = 0x500;
            public const int RF_CMD = WM_USER + 13;
            public struct RFDataStruct
            {
                public int rfLength;
                public string rfData;
            }        byte rfCmd = 0;        [DllImport("user32.dll")]
            public static extern bool SendMessage(IntPtr hWnd, int Msg, int wParam, ref RFDataStruct lparam);        [DllImport("user32.dll")]
            public static extern bool SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lparam);        [DllImport("user32.dll")]
            public static extern bool SendMessage(IntPtr hWnd, int Msg, byte wParam, int lparam);        private void buttonSend_Click(object sender, EventArgs e)
            {
                Process[] vProcesses = Process.GetProcessesByName("PorcessReceiveUserDefinedMessageDemo"); // 查询目标进程
                if (vProcesses.Length <= 0)
                    vProcesses = Process.GetProcessesByName("PorcessReceiveUserDefinedMessageDemo.vshost");  //Debug调试进程
                if (vProcesses.Length <= 0)
                {
                    MessageBox.Show("目标进程没有找到!");
                    return;
                }            if (comboBoxRF.Text == comboBoxRF.Items[0].ToString()) rfCmd = 0;
                else if (comboBoxRF.Text == comboBoxRF.Items[1].ToString()) rfCmd = 1;
                else if (comboBoxRF.Text == comboBoxRF.Items[2].ToString()) rfCmd = 2;  //SelectedText不行,始终为空
                else rfCmd = 3;
                string rfCmdString = rfCmd.ToString("X2");            //RFDataStruct rfMessage = new RFDataStruct();
                //rfMessage.rfData = rfCmdString;
                //rfMessage.rfLength = rfMessage.rfData.Length;            //IntPtr rfIntPtr = Marshal.StringToHGlobalAuto(rfCmdString);  //乱码
               // IntPtr rfIntPtr = Marshal.StringToHGlobalUni(rfCmdString);     //乱码
                //IntPtr rfIntPtr = Marshal.AllocHGlobal(1);
                //Marshal.WriteByte(rfIntPtr, rfCmd);            foreach (Process vProcess in vProcesses)
                {
                    //bool returnValue3 = SendMessage(vProcess.MainWindowHandle, RF_CMD, 1, ref rfMessage);
                    //bool returnValue3 = SendMessage(vProcess.MainWindowHandle, RF_CMD, 1, rfIntPtr);
                    bool returnValue3 = SendMessage(vProcess.MainWindowHandle, RF_CMD, rfCmd, 1);
                }
                //Marshal.FreeHGlobal(rfIntPtr);
            }接收方:
      public const int WM_USER = 0x500;
            public const int RF_CMD = WM_USER + 13;        public struct RFDataStruct
            {
                public string rfData;
                public int rfLength;
            }        protected override void DefWndProc(ref Message m)
            {
                switch (m.Msg)
                {
                    case RF_CMD:
                        //RFDataStruct rfDataStruct = new RFDataStruct();
                        //Type type = rfDataStruct.GetType();
                        //rfDataStruct = (RFDataStruct)m.GetLParam(type);
                        //string rfCmd = rfDataStruct.rfData;                    //string rfCmd = Marshal.PtrToStringAuto(m.LParam);
                        //string rfCmd = Marshal.PtrToStringUni(m.LParam);
                        //textBox1.Text = rfCmd;                    //byte rfCmd = Marshal.ReadByte(m.LParam);
                        //textBox1.Text = rfCmd.ToString();                    //byte rfCmd= (byte)m.GetLParam(typeof(byte));  //有异常
                        byte rfCmd = (byte)m.WParam;
                        textBox1.Text = rfCmd.ToString();                  
                        break;
                    default:
                        base.DefWndProc(ref m);
                        break;
                }
                //base.WndProc(ref m);
            }