如果一个串口已经被其它程序打开,我怎样在程序中读取(监视)该端口的数据?就象PORTMON一样.

解决方案 »

  1.   

    http://www.codeguru.com/network/commspy.shtml
      

  2.   

    approach() :http://www.codeguru.com/network/commspy.shtml上的不能监视已经被别人打开的串口.
      

  3.   

    我也想知道,我在MSDN中看到这个函数,可能可以试试,由于没有时间亲自试,楼主如果试成功的话一定要把经验共享啊!
    BOOL DuplicateHandle(
      HANDLE hSourceProcessHandle,  // handle to the source process
      HANDLE hSourceHandle,         // handle to duplicate
      HANDLE hTargetProcessHandle,  // handle to process to duplicate to
      LPHANDLE lpTargetHandle,  // pointer to duplicate handle
      DWORD dwDesiredAccess,    // access for duplicate handle
      BOOL bInheritHandle,      // handle inheritance flag
      DWORD dwOptions           // optional actions
    )
      

  4.   

    PortMon用的应该不是这个方法。强烈关注
      

  5.   

    PortMon用的可能是替换设备驱动程序的方法。
      

  6.   

    sbw(清风一笑)     CAO   这也行? 不是一台机了
      

  7.   

    Saimen(单身情人)  虽不是一台机,但是这也是一种方法呀。
      

  8.   

    不能用两个串口或两台机器,启动自己的程序,监视一个已经被打开串口的收、发数据。大家可以下载一个PortMon程序,体验一下。如果用到设备驱动一级,那肯定与操作系统有关。roaringwind(www.gjwtech.com)能说的具体点吗?
      

  9.   

    呵呵,sbw(清风一笑) 的主意我倒是真的用过,为了测试的话好像真的挺省事的,:)
    不过不用两个机器啊,做一根线,两个头,一般机器都是两个串口么,都插上,只管读
    另外一个就可以了,要是非用driver,wdm的就行了吧,在port class 加一个过滤,我在2K上干过,98应该也没问题,反正不大会有人再坚持用95了吧
      

  10.   

    // 工作者线程,负责监视串行口
    UINT CommProc(LPVOID pParam)
    {
    OVERLAPPED os;
    DWORD dwMask, dwTrans;
    COMSTAT ComStat;
    DWORD dwErrorFlags;
    CNcfileCtrlDlg *pDoc = (CNcfileCtrlDlg*)pParam;
    memset(&os, 0, sizeof(OVERLAPPED));
    os.hEvent=CreateEvent(NULL, TRUE, FALSE, NULL);
    if(os.hEvent == NULL)
    {
    ::MessageBox(NULL,"不能创建事件对象!","警告", 
    MB_ICONWARNING | MB_OK);
    return (UINT)-1;
    }
    while(pDoc->m_bConnected)
    {
    ClearCommError(pDoc->m_hCom,&dwErrorFlags,&ComStat);
    if(ComStat.cbInQue)
    {
    // 无限等待WM_COMMNOTIFY消息被处理完
    WaitForSingleObject(pDoc->m_hPostMsgEvent, INFINITE);
    ResetEvent(pDoc->m_hPostMsgEvent);//置为无信号
    // 通知对话框
    PostMessage(pDoc->m_hTermWnd, WM_COMMNOTIFY, EV_RXCHAR, 0);
    continue;
    } dwMask = 0;
    if(!WaitCommEvent(pDoc->m_hCom, &dwMask, &os)) // 重叠操作,等待SetCommMask设定的事件出现
    {
    if(GetLastError() == ERROR_IO_PENDING)
    {
    // 无限等待重叠操作结果,如果EV_RXCHAR事件发生(串口收到字符并放入输入缓冲区中)
    // 那么函数就结束等待。
    GetOverlappedResult(pDoc->m_hCom, &os, &dwTrans, TRUE);
    }
    else
    {
    CloseHandle(os.hEvent);
    return (UINT)-1;
    }
    }

    }
    CloseHandle(os.hEvent); pDoc->ReceiveThread = false; return 0;  // 线程正常结束
    }
    // 工作者线程,负责发送数据
    UINT CommProcT(LPVOID pParam)
    {

    DWORD FileLength;
    DWORD Remainder;  // 余数
    DWORD Size;       // 进程条每一格的字符数
    DWORD j = 0;
    BOOL fState;
    DWORD length,dwLength = 1;  // 成功写入缓冲区的字符数
    COMSTAT ComStat;
    DWORD dwErrorFlags;
    /*
    HWND hwnd;
    CNcfileCtrlDlg dlg;
    hwnd=dlg.GetSafeHwnd();
    CNcfileCtrlDlg *pDoc=(CNcfileCtrlDlg *)GetWindow(hwnd,GW_OWNER);
    */
    CNcfileCtrlDlg *pDoc = (CNcfileCtrlDlg*)pParam;
    FileLength = pDoc->m_sNcFile.GetLength();    Remainder = FileLength%20;  // 进程条范围从0到20
    Size = (FileLength-Remainder)/20; for(DWORD i=0; i<FileLength; i++)
    {
    char m_cChar;
    if(i%Size == 0)      // 显示进度
    {
    pDoc->m_cProgress.SetPos(j);
    j++;
    }
    if(i == (FileLength-1))
    pDoc->m_cProgress.SetPos(20);
            
    if(WaitForSingleObject(pDoc->m_hKillThreadT,0)==WAIT_OBJECT_0) //终止线程事件有信号
    {
                pDoc->GetDlgItem(IDC_STOPT)->EnableWindow(FALSE);
    pDoc->GetDlgItem(IDC_RECEIVE)->EnableWindow(TRUE);
    pDoc->GetDlgItem(IDC_SENDING)->EnableWindow(TRUE);
    pDoc->BeginThread=false;
    //终止监视通信事件线程
    TerminateThread(pDoc->m_pThreadEvent->m_hThread,0);
    pDoc->EventThread=false;
    AfxEndThread(0);   //退出线程
    } if(pDoc->m_bXon)
    WaitForSingleObject(pDoc->m_hXonEvent,INFINITE);
    if(pDoc->m_bRts)
    WaitForSingleObject(pDoc->m_hRtsEvent,INFINITE);
    if(pDoc->m_bDsr)
    WaitForSingleObject(pDoc->m_hDtrEvent,INFINITE); m_cChar = pDoc->m_sNcFile.GetAt(i);
    ClearCommError(pDoc->m_hCom,&dwErrorFlags,&ComStat);
    fState = WriteFile(pDoc->m_hCom,&m_cChar,dwLength,&length,&pDoc->m_osWrite);
    if(!fState){
    if(GetLastError() == ERROR_IO_PENDING)   //写操作被挂起
    {
    if(!GetOverlappedResult(pDoc->m_hCom,&pDoc->m_osWrite,&length,TRUE)) //写操作没有成功完成
    {
    ::MessageBox(NULL,"发送代码出现错误!","错误", 
    MB_ICONERROR | MB_OK);
    }
    }
    else
    length=0;
    }

    if(!length)
    {
    ::MessageBox(NULL,"发送代码出现错误,可能机床没准备好!","错误", 
    MB_ICONERROR | MB_OK);
    pDoc->GetDlgItem(IDC_SENDING)->EnableWindow(TRUE);
                pDoc->GetDlgItem(IDC_RECEIVE)->EnableWindow(TRUE);
            pDoc->GetDlgItem(IDC_STOPT)->EnableWindow(FALSE);
            pDoc->GetDlgItem(IDC_STOPING)->EnableWindow(FALSE);// return (UINT)-1;
    pDoc->BeginThread = false;
    TerminateThread(pDoc->m_pThreadEvent->m_hThread,0);
    pDoc->EventThread = false;
    AfxEndThread(0);   //退出线程
    }
    }
    pDoc->GetDlgItem(IDC_SENDING)->EnableWindow(TRUE);
        pDoc->GetDlgItem(IDC_RECEIVE)->EnableWindow(TRUE);
    pDoc->GetDlgItem(IDC_STOPT)->EnableWindow(FALSE);
    pDoc->GetDlgItem(IDC_STOPING)->EnableWindow(FALSE); pDoc->BeginThread = false;
        //终止监视通信事件线程
    TerminateThread(pDoc->m_pThreadEvent->m_hThread,0);
    pDoc->EventThread = false;

    if(::MessageBox(NULL,"发送完毕!","提示", MB_ICONINFORMATION | MB_OK) == IDOK)//;
    {
    pDoc->m_cProgress.SetPos(0);
    }
    /* if(AfxMessageBox("发送完毕!",MB_OKCANCEL) == IDOK)
    {


    int m_iNumber;
    int m_iLine;
    LPSTR buf;
    CString m_sTemp1;
    buf = m_sTemp1.GetBuffer(2048);
    m_iLine = pDoc->m_cNcFile.GetLineCount();
    m_iNumber = pDoc->m_cNcFile.GetLine(m_iLine,buf,2048);
    buf[m_iNumber] = '\0';
    m_sTemp1.ReleaseBuffer();
    pDoc->m_sEnd = buf;
    pDoc->UpdateData(false);
    }*/ return 0; //线程正常结束}
    // 工作者线程,负责监测通信事件
    UINT CommProcEvent(LPVOID pParam)
    {
    DWORD dwCommEvent = 0,dwTrans,dwModemStatus;
    DWORD dwStoredFlags;
    OVERLAPPED osStatus = {0};
    char buf;
    BOOL fCTS,fDSR;
    DWORD length = 1; CNcfileCtrlDlg *pDoc = (CNcfileCtrlDlg*)pParam;
    dwStoredFlags = EV_CTS | EV_DSR | EV_RXCHAR;  // 设置事件掩码
    SetCommMask(pDoc->m_hCom,0);
    if(!SetCommMask(pDoc->m_hCom,dwStoredFlags))
    {
    pDoc->EventThread = false;
    return 0;
    } // 为重叠osStatus创建事件对象,手工重置,初始化为无信号的
    osStatus.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
    if(osStatus.hEvent == NULL)
    {
    return 0;
    pDoc->EventThread = false;
    } if(!GetCommModemStatus(pDoc->m_hCom,&dwModemStatus))
    {
    ::MessageBox(NULL,"不能获得针脚电压状态!","警告", MB_ICONWARNING | MB_OK);
    pDoc->EventThread = false;
    return 0;
    }
    else
    {
    // RTS/CTS流控协议
    fCTS = MS_CTS_ON &dwModemStatus;
    if(fCTS)
    SetEvent(pDoc->m_hRtsEvent); // 置为有信号,可以发送;
    else
    ResetEvent(pDoc->m_hRtsEvent); // 置为无信号,不能发送; // DTR/DSR流控协议
    fDSR = MS_DSR_ON & dwModemStatus;
    if(fDSR)
    SetEvent(pDoc->m_hDtrEvent); // 置为有信号,可以发送
    else
    ResetEvent(pDoc->m_hDtrEvent); // 置为无信号,不能发送
    } while(pDoc->m_bConnected)
    {
    if(!WaitCommEvent(pDoc->m_hCom, &dwCommEvent, &osStatus)) // 重叠操作,等待SetCommMask设定的事件出现
    {
    if(GetLastError() == ERROR_IO_PENDING)
    {
    // 无限等待重叠操作结果,如果设定的事件发生,那么函数就结束等待。
    GetOverlappedResult(pDoc->m_hCom, &osStatus, &dwTrans, TRUE);
    }
    // XON/XOFF协议
    if ( ( dwCommEvent & EV_RXCHAR ) == EV_RXCHAR )  
    {
    ReadFile(pDoc->m_hCom,&buf,length,&length,&pDoc->m_osRead);
    if(buf == XOFF)
    ResetEvent(pDoc->m_hXonEvent);  // 置为无信号,不能发送;
    if(buf == XON)
    SetEvent(pDoc->m_hXonEvent);    // 置为有信号,可以发送;
    }
    // RTS/CTS协议
    if ( ( dwCommEvent & EV_CTS ) == EV_CTS )  
    {
    if(!GetCommModemStatus(pDoc->m_hCom,&dwModemStatus))
    {
    ::MessageBox(NULL,"不能获得针脚电压状态!","警告", MB_ICONWARNING | MB_OK);
    pDoc->EventThread = false;
    return 0;
    }
    else
    {
    fCTS = MS_CTS_ON &dwModemStatus;
    if(fCTS)
    SetEvent(pDoc->m_hRtsEvent);    // 置为有信号,可以发送;
    else
    ResetEvent(pDoc->m_hRtsEvent);  // 置为无信号,不能发送;
    }
    }
    // DTR/DSR协议
    if ( ( dwCommEvent & EV_DSR ) == EV_DSR )
    {
    if(!GetCommModemStatus(pDoc->m_hCom,&dwModemStatus))
    {
    ::MessageBox(NULL,"不能获得针脚电压状态!","警告", MB_ICONWARNING | MB_OK);
    pDoc->EventThread = false;
    return 0;
    }
    else
    {
    fDSR = MS_DSR_ON & dwModemStatus;
    if(fDSR)
    SetEvent(pDoc->m_hDtrEvent);   // 置为有信号,可以发送
    else
    ResetEvent(pDoc->m_hDtrEvent); // 置为无信号,不能发送
    }
    }
    }
    }//////////////////////////////////////////////////////////////////////
    // 测试代码
    //   CNcfileCtrlDlg *pDoc=(CNcfileCtrlDlg*)pParam;
    // while(pDoc->m_bConnected)
    // {
    // WaitForSingleObject(pDoc->m_hRtsEvent,10000);
    // SetEvent(pDoc->m_hXonEvent); 
    // }
    ///////////////////////////////////////////////////////////////////////
    pDoc->Eve
      

  11.   

    hook api
    直接hook ReadFile,WriteFile不就搞定了
      

  12.   

    我也想用hook,怎么hook?  yousen(一个人流浪)
      

  13.   

    请问 nuaawyd(神啊,救救我吧!) :CNcfileCtrlDlg作了什么事?