进程间通信,使用WM_COPYDATA消息在两个程序间传递字符串,有问题。

时间:2022-10-20 14:01:41
发送端:

    public partial class Form1 : Form
    {
       
        public Form1()
        {
            InitializeComponent();
        }

        public const int WM_COPYDATA = 0x004A;

        [DllImport("User32.dll", EntryPoint = "FindWindow")]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);  

        [StructLayout(LayoutKind.Sequential)]
        public struct CopyDataStruct
        {
            public IntPtr dwData; // 附加参数  
            public int cbData; // 数据大小
            public IntPtr lpData; // 数据内容
        }

        [DllImport("user32.dll")]
        public static extern bool SendMessage(
            IntPtr hWnd, int Msg, int wParam, IntPtr lParam);

        private void button1_Click(object sender, EventArgs e)
        {
            string S = textBox1.Text;
            if (S.Length <= 0)
            {
                Console.WriteLine("内容为空");
                return;
            }

            string processName = "WMCopyDataB";
            Process[] vProcesses = Process.GetProcessesByName(processName); // 查询目标进程

            if (vProcesses.Length <= 0)
                vProcesses = Process.GetProcessesByName(processName + ".vshost"); // 处理调试运行

            if (vProcesses.Length <= 0)
            {
                MessageBox.Show("目标进程没有找到");
                return;
            }

            ////string strDlgTitle = "processRecv";
            //string strDlgTitle = "WMCopyDataB";
            ////接收端的窗口句柄  
            //IntPtr hwndRecvWindow = FindWindow(null, strDlgTitle);
            //if (hwndRecvWindow == IntPtr.Zero)
            //{
            //    MessageBox.Show("请先启动接收消息程序");
            //    return;
            //}  

            CopyDataStruct vCopyDataStruct = new CopyDataStruct();
            vCopyDataStruct.dwData = (IntPtr)0;
            vCopyDataStruct.cbData = S.Length * sizeof(char) + sizeof(char); // 最后结束字符\x00
            Debug.WriteLine(vCopyDataStruct.cbData);
            vCopyDataStruct.lpData = Marshal.StringToBSTR(S);
            IntPtr vAddress = Marshal.AllocCoTaskMem(Marshal.SizeOf(vCopyDataStruct));
            Marshal.StructureToPtr(vCopyDataStruct, vAddress, true);
            foreach (Process vProcess in vProcesses)
            {
                SendMessage(vProcess.MainWindowHandle, WM_COPYDATA, 0, vAddress); // 发送结构
            }
            Marshal.FreeBSTR(vCopyDataStruct.lpData);
            Marshal.FreeCoTaskMem(vAddress);
            
        }
    }

接收端:

public partial class Form1 : Form
    {
        [DllImport("User32.dll")]
        public static extern bool ChangeWindowMessageFilter(uint msg, int flags);

        public Form1()
        {
            InitializeComponent();
            //ChangeWindowMessageFilter(WM_COPYDATA, 1);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            ChangeWindowMessageFilter(WM_COPYDATA, 1);  //**注册WM_COPYDATA消息,避免在win7中以管理员方式运行,过滤掉该消息。
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct CopyDataStruct
        {
            public IntPtr dwData; // 附加参数 
            public int cbData; // 数据大小
            public IntPtr lpData; // 数据内容
        }

        public const int WM_COPYDATA = 0x004A;

        protected override void DefWndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case WM_COPYDATA:
                    CopyDataStruct vCopyDataStruct = (CopyDataStruct)Marshal.PtrToStructure(
                        m.LParam, typeof(CopyDataStruct));
                    string S = Marshal.PtrToStringBSTR(vCopyDataStruct.lpData);
                    textBox1.Text = S;
                    break;
            }
            base.DefWndProc(ref m);
        }
    }

有问题,不能正常接收,问题出在哪啊?

6 个解决方案

#1


这个主要还是自己调试.
1, sendmessage 和 postmessage.
2. 能不能找到要接收消息的窗口; 接收端 是否能接受到消息; 消息中附带的数据能否正常解析.

#2


长见识了,从来没用过这种方式进行进程间通信。我一般使用共享内存、命名管理和Socket。

#3


引用 1 楼 bambuz 的回复:
这个主要还是自己调试.
1, sendmessage 和 postmessage.
2. 能不能找到要接收消息的窗口; 接收端 是否能接受到消息; 消息中附带的数据能否正常解析.

问题是出在接收端“CopyDataStruct vCopyDataStruct = (CopyDataStruct)Marshal.PtrToStructure(
                        m.LParam, typeof(CopyDataStruct));”  Out of Memory,但是我不知道为什么会出现这样的问题。

#4


引用 2 楼 lincolnandlinda 的回复:
长见识了,从来没用过这种方式进行进程间通信。我一般使用共享内存、命名管理和Socket。

后面三种听说过,没用过,这种最简单,哈哈哈。

#5


用BSTR是错的。因为BSTR指针指向的字符串前面有长度信息(就是那个05 00 00 00):

          BSTR指针
             |
             v
05 00 00 00 'h' 'e' 'l' 'l' 'o' 00

当WM_COPYDATA帮你把数据(BSTR指针指向的数据)拷贝到其他进程时,只会拷贝'hello\0',并不会把前置长度05 00 00 00拷贝过去。
当目标进程还原BSTR时,‘'hello\0'前面可以是任意的垃圾,比如长度变成789272521等。这可能导致你内存溢出或非法访问。

#6


引用 5 楼 Forty2 的回复:
用BSTR是错的。因为BSTR指针指向的字符串前面有长度信息(就是那个05 00 00 00):

          BSTR指针
             |
             v
05 00 00 00 'h' 'e' 'l' 'l' 'o' 00

当WM_COPYDATA帮你把数据(BSTR指针指向的数据)拷贝到其他进程时,只会拷贝'hello\0',并不会把前置长度05 00 00 00拷贝过去。
当目标进程还原BSTR时,‘'hello\0'前面可以是任意的垃圾,比如长度变成789272521等。这可能导致你内存溢出或非法访问。

原来是这样,我换成其它方式确实可以了。

#1


这个主要还是自己调试.
1, sendmessage 和 postmessage.
2. 能不能找到要接收消息的窗口; 接收端 是否能接受到消息; 消息中附带的数据能否正常解析.

#2


长见识了,从来没用过这种方式进行进程间通信。我一般使用共享内存、命名管理和Socket。

#3


引用 1 楼 bambuz 的回复:
这个主要还是自己调试.
1, sendmessage 和 postmessage.
2. 能不能找到要接收消息的窗口; 接收端 是否能接受到消息; 消息中附带的数据能否正常解析.

问题是出在接收端“CopyDataStruct vCopyDataStruct = (CopyDataStruct)Marshal.PtrToStructure(
                        m.LParam, typeof(CopyDataStruct));”  Out of Memory,但是我不知道为什么会出现这样的问题。

#4


引用 2 楼 lincolnandlinda 的回复:
长见识了,从来没用过这种方式进行进程间通信。我一般使用共享内存、命名管理和Socket。

后面三种听说过,没用过,这种最简单,哈哈哈。

#5


用BSTR是错的。因为BSTR指针指向的字符串前面有长度信息(就是那个05 00 00 00):

          BSTR指针
             |
             v
05 00 00 00 'h' 'e' 'l' 'l' 'o' 00

当WM_COPYDATA帮你把数据(BSTR指针指向的数据)拷贝到其他进程时,只会拷贝'hello\0',并不会把前置长度05 00 00 00拷贝过去。
当目标进程还原BSTR时,‘'hello\0'前面可以是任意的垃圾,比如长度变成789272521等。这可能导致你内存溢出或非法访问。

#6


引用 5 楼 Forty2 的回复:
用BSTR是错的。因为BSTR指针指向的字符串前面有长度信息(就是那个05 00 00 00):

          BSTR指针
             |
             v
05 00 00 00 'h' 'e' 'l' 'l' 'o' 00

当WM_COPYDATA帮你把数据(BSTR指针指向的数据)拷贝到其他进程时,只会拷贝'hello\0',并不会把前置长度05 00 00 00拷贝过去。
当目标进程还原BSTR时,‘'hello\0'前面可以是任意的垃圾,比如长度变成789272521等。这可能导致你内存溢出或非法访问。

原来是这样,我换成其它方式确实可以了。