最近接一个任务,要求写一个接口程序,需要要与其他的Win32程序交换信息.
正在使用调用 API 发送 Win32消息的方式实现.
经过几天的查找与实验,与C#程序间的通信已经解决(十分感谢CSDN里的各位大大)但与VB间传递字符串的时候出现问题.
描述如下:C#方,定义要发送的消息的结构为:
    /// <summary>
    ///  发送WM_COPYDATA消息的数据结构
    /// </summary>
    internal struct MESSAGE_STRUCT
    {
        /// <summary>
        ///  用户自定义数据
        /// </summary>
        public int dwData;
        /// <summary>
        ///  数据长度
        /// </summary>
        public int cbData;
        /// <summary>
        ///  数据首地址指针
        ///</summary>
        [MarshalAs(UnmanagedType.LPStr)]
        public string lpData;
    }发送语句为:
NativeMethods.SendMessage(this.SoftHandle, NativeMethods.WM_COPYDATA, messageType, ref data);
其中,对方句柄已知(对方能够收到消息),messageType 为自定义的数据,整数101, data是按照上面的定义,每一项都有相应的值:
                MESSAGE_STRUCT data = new MESSAGE_STRUCT();
                // 自定义整形内容
                data.dwData = messageType;
                // 传递要发送的数据的长度 + \x00
                data.cbData = System.Text.Encoding.Default.GetBytes(message).Length + 1;
                // 传递要发送的数据的地址指针
                data.lpData = message;现在的问题是在VB侧,无法读出发送过来的内容.我尝试过定义这样的自定义类型:'''  发送WM_COPYDATA消息的数据结构
Type MESSAGE_STRUCT    '''  用户自定义数据
    dwData As Long    '''  数据长度
    cbData As Long    '''  数据首地址指针
    lpData As String * 1000
End Type可是,读取到的前两个数值为0,第三个字符串为乱码.请各位大大救命呀!我已经苦恼好几天了!!!

解决方案 »

  1.   

    进程间通信,我一般都用ActiceX EXE。
    虽然多了一个进程,但操作起来非常方便,还可以多个进程捕捉同一个进程的事件和数据。如果感兴趣的话,我再另外回复你。
      

  2.   

    你VB端是如何接收的?其它的不说,至少VB里面的结构体定义是错的: lpData As String * 1000 
    VB中的String类型(BSTR)与LPSTR根本不是同一类型,你需要改为Long去接收这个指针,然后从指向的区域读出字符串数据
      

  3.   

    对不起.有事情况昨天没大说具体.  首先,我在C#间用SendMessage发字符串信息的时候,试过很多种情况,发现 WM_COPYDATA 这个常数是必须要用的,否则接收时会报"试图访问受保护的内存"的错误;另外,MESSAGE_STRUCT 这个结构体的格式是固定的,如果只放一个字符串,甚至如果 cbData 这个长度没有赋值,接收方都会报错.  其次,在接收方,我的接收方式是这样的:
        第一步,挂载 WindowProc 方法来处理接收到的消息
          pOld = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WindowProc)  
          这个方法的定义为:
             Public Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, _
                 ByVal wParam As Long, ByVal lParam As Long) As Long
          所以,lParam 应该接收到的是对方发来的 LParam 这个参数的指针(在其他的消息中已经证实).
        第二步,在这个方法中,我定义了一个上述的结构对象:
            Dim getStruct As MESSAGE_STRUCT
        然后,用
            ReadProcessMemory ToHandle, lParam, ByVal VarPtr(getStruct), 1008, stringLeng
        的方法,试图复制出发送过来的内容,但是,结果是前两个数字(Long类型)都为0.第三个得到的是一长串'r'.  我Win32下的开发,以及信息的格式和约定等方面,都比较没有经验,请各位达人,不吝赐教!  谢谢,今天会在线等待的.   
      

  4.   

    通过网上的疯狂搜索,终于解决了这个问题.通过分析在 北京软件产业基地 的 开放源码库中,以下位置的 PrevInst 源码,找到并解决了问题.简单描述一下,以便于有类似开发需要的同行们共同研究:首先,引用这个 API :
    Private Declare Sub CopyMem Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)然后,分两次复制出内存的内容:
      第一次:
          CopyMem getStruct, ByVal lParam, Len(getStruct)
          得到结构体内的三个整数.(getStruct 为结构体变量)
          '''  发送WM_COPYDATA消息的数据结构
           结构体为:
              Type MESSAGE_STRUCT
                 '''  用户自定义数据
                   dwData As Long
                 '''  数据长度
                   cbData As Long
                 '''  数据首地址指针
                   lpData As Long
               End Type    ' (感谢 San_zc_1, 他的意见是对的)
      第二次:
          CopyMem ByVal StrPtr(getString), ByVal getStruct.lpData, getStruct.cbData
          这里复制出字符串的内容.getString 为定义的字符串变量.
          在这个位置,需要注意一点:在C#中,传递出来的是Unicdoe的字符串,需要作相应的转换:
               getString = StrConv(getString, vbUnicode)
    至此,在VB6中,得到C#传递出来的内容.PrevInst 的源码下载页面为:
      http://osl.bsw.net.cn/showFiles.php?group_id=15182&release_id=12561
    在此,一并向无私开源,为国人的技术提高与进步,做出贡献的所有人,致以敬意!!!
    ( 有感于最近连环信的铺天盖地, 对默默工作的我们, 赞一个!)