zoukankan      html  css  js  c++  java
  • 关于使用WM_COPYDATA进行进程之间交换数据的问题

    在开发中需要实现两个进程间通讯并交换数据。实现进程间通讯有多种方法,例如下面的(摘自http://www.yuanma.org/data/2006/1213/article_1945.htm):

    0。剪贴板Clipboard: 在16位时代常使用的方式,CWnd中提供支持

    1。窗口消息 标准的Windows消息以及专用的WM_COPYDATA消息 SENDMESSAGE()接收端必须有一个窗口

    2。使用共享内存方式(Shared Memory)
       a.设定一块共享内存区域           
         HANDLE CreateFileMapping(HANDLE,LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD,  LPCSTR) 
         产生一个file-mapping核心对象
         LPVOID MapViewOfFile(
             HANDLE hFileMappingObject,
             DWORD  dwDesiredAcess,
             DWORD  dwFileOffsetHigh,
             DWORD  dwFileOffsetLow,
             DWORD  dwNumberOfBytesToMap
         );
        得到共享内存的指针
       b.找出共享内存
        决定这块内存要以点对点(peer to peer)的形式呈现
            每个进程都必须有相同的能力,产生共享内存并将它初始化。每个进程
            都应该调用CreateFileMapping(),然后调用GetLastError().如果传回的
            错误代码是ERROR_ALREADY_EXISTS,那么进程就可以假设这一共享内存区         域已经被别的进程打开并初始化了,否则该进程就可以合理的认为自己 排在第          一位,并接下来将共享内存初始化。
        还是要使用client/server架构中
           只有server进程才应该产生并初始化共享内存。所有的进程都应该使用

    HANDLE OpenFileMapping(DWORD dwDesiredAccess,
                                       BOOL bInheritHandle,
                                       LPCTSTR lpName);
            再调用MapViewOfFile(),取得共享内存的指针
       c.同步处理(Mutex)
       d.清理(Cleaning up) BOOL UnmapViewOfFile(LPCVOID lpBaseAddress);
                            CloseHandle()

    3。动态数据交换(DDE)通过维护全局分配内存使的应用程序间传递成为可能
       其方式是再一块全局内存中手工放置大量的数据,然后使用窗口消息传递内存    指针.这是16位WIN时代使用的方式,因为在WIN32下已经没有全局和局部内存    了,现在的内存只有一种就是虚存。  

    4。消息管道(Message Pipe)
       用于设置应用程序间的一条永久通讯通道,通过该通道可以象自己的应用程序
       访问一个平面文件一样读写数据。
       匿名管道(Anonymous Pipes)
           单向流动,并且只能够在同一电脑上的各个进程之间流动。
       命名管道(Named Pipes)
           双向,跨网络,任何进程都可以轻易的抓住,放进管道的数据有固定的格        式,而使用ReadFile()只能读取该大小的倍数。
           可以被使用于I/O Completion Ports

    5   邮件槽(Mailslots)
        广播式通信,在32系统中提供的新方法,可以在不同主机间交换数据,在        WIN9X下只支持邮件槽客户

    6。Windows套接字(Windows Socket)
       它具备消息管道所有的功能,但遵守一套通信标准使的不同操作系统之上的应    用程序之间可以互相通信。

    7。Internet通信 它让应用程序从Internet地址上载或下载文件

    8。RPC:远程过程调用,很少使用,因其与UNIX的RPC不兼容。

    9。串行/并行通信(Serial/Parallel Communication)
       它允许应用程序通过串行或并行端口与其他的应用程序通信

    10。COM/DCOM 
         通过COM系统的代理存根方式进行进程间数据交换,但只能够表现在对接口     函数的调用时传送数据,通过DCOM可以在不同主机间传送数据。

     

    衡量各种实现的技术和功能的情况,选用了通过窗口消息的办法。

     发送消息:

    LPCWSTR strPkmp = PKMP_DDE_WND_CLASS;
    HWND hWndMain = ::FindWindow(strPkmp, NULL);
    if(NULL != hWndMain)
    {
    CComBSTR bstrSend(bstrTitle);
    bstrSend.Append(L"*#&*");
    bstrSend.AppendBSTR(bstrUrl);
    COPYDATASTRUCT cData;
    cData.dwData = 0;
    cData.cbData = wsclen(bstrSend);
    cData.lpData = bstrSend;
    ::SendMessage(hWndMain,WM_COPYDATA,NULL,(LPARAM)&cData);
    //::MessageBoxW(NULL,bstrSend,L"T",MB_OK);

    接收消息:

     CString strRecv = CString(pCopyDataStruct->lpData);

    int idx = strRecv.Find(L"*#&*");
    if(idx > 0)
    {
    CString strTitle = strRecv.Left(idx);
    CString strUrl = strRecv.Right(strRecv.GetLength() - idx - 4);
    }

    发现接收的消息都不完整,只收到一小部分。

     万能的Google,终于找到原因,原来用WM_COPYDATA只能传输ANSI编码。

    修改如下:

    发送数据: 

    if(NULL != hWndMain)
    {
    CComBSTR bstrSend(bstrTitle);
    bstrSend.Append(L"*#&*");
    bstrSend.AppendBSTR(bstrUrl);

    //转换成char* 

    _bstr_t b = bstrSend;
    LPSTR lpStr = b;
    COPYDATASTRUCT cData;
    cData.dwData = 0;
    cData.cbData = strlen(lpStr);
    cData.lpData = lpStr;
    ::SendMessage(hWndMain,WM_COPYDATA,NULL,(LPARAM)&cData);
    //::MessageBoxW(NULL,bstrSend,L"T",MB_OK);

    接收数据: 

     LPSTR lpStr = (LPSTR)(pCopyDataStruct->lpData);

    *(lpStr + pCopyDataStruct->cbData) = '\0';
    LPCWSTR lpWStr = Ansi2Unicode(lpStr);
    //int nLen = wcslen(lpWStr);
    CString strRecv = CString(lpWStr);
    //strRecv = strRecv.Left(pCopyDataStruct->cbData);
    int idx = strRecv.Find(L"*#&*");
    if(idx > 0)
    {
    CString strTitle = strRecv.Left(idx);
    CString strUrl = strRecv.Right(strRecv.GetLength() - idx - 4);
    }

    搞定!!! 

  • 相关阅读:
    HDU1013 Digital Roots
    DP---背包问题
    新生代与老年代
    JVM常见问题(二)
    JVM常见问题 一(转载)
    JVM内存模型及分区
    (转载)JVM知识小集
    类加载机制:全盘负责和双亲委托
    mysql 函数GROUP_CONCAT(temp.amount SEPARATOR ',')的用法
    mysql优化--explain关键字
  • 原文地址:https://www.cnblogs.com/wantfly/p/WTL.html
Copyright © 2011-2022 走看看