从管道块和死锁读取

时间:2013-11-02 08:01:21

标签: c++ winapi pipe blocking readfile

我正在开发一个类似程序的远程shell。在远程计算机上运行命令我创建了一个cmd.exe进程,并将其stdin和stdout重定向到一对管道。 我使用这些管道发送命令并获得结果。 我使用ReadFile函数从cmd.exe返回命令的输出,但我不知道 我必须从管道中读取的确切数据量。所以如果数据没有准备好readfile 进入阻止模式并等待数据。

我使用的是MSVC ++ 2010,我的操作系统是Win7。以下是我的代码的一部分作为示例:

void CpipesDlg::OnBnClickedBtnredirstd()
{
    char Cmd[]="dir *.*\r\n";
    char Buff[129];
    CString str;
    HANDLE hStdIn_Read, hStdIn_Write;
    HANDLE hStdOut_Read, hStdOut_Write;
    SECURITY_ATTRIBUTES sAttr;

    STARTUPINFOA StartInf;
    PROCESS_INFORMATION procInf;

    DWORD dwBytesToWrite,dwBytesReadFrom;

    sAttr.nLength = sizeof(sAttr);
    sAttr.bInheritHandle = TRUE;
    sAttr.lpSecurityDescriptor = NULL;

    CreatePipe(&hStdIn_Read,&hStdIn_Write,&sAttr,0);
    CreatePipe(&hStdOut_Read,&hStdOut_Write,&sAttr,0);

    //SetHandleInformation(hStdIn_Read, HANDLE_FLAG_INHERIT, 0);
    //SetHandleInformation(hStdIn_Write, HANDLE_FLAG_INHERIT, 0);

    memset(&StartInf,0, sizeof(StartInf));
    memset(&procInf,0,sizeof(procInf));

    StartInf.cb = sizeof(StartInf);
    StartInf.dwFlags = STARTF_USESTDHANDLES;
    StartInf.hStdError = hStdOut_Write;
    StartInf.hStdOutput = hStdOut_Write;
    StartInf.hStdInput = hStdIn_Read;

    WriteFile(hStdIn_Write,Cmd,sizeof(Cmd),&dwBytesToWrite,NULL);

    if(!CreateProcessA(NULL,"cmd.exe",NULL,NULL,TRUE,NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW ,NULL,NULL,&StartInf,&procInf))
    {
        MessageBoxA(m_hWnd, "Can't Create Process","Error",MB_OK | MB_ICONERROR);
    }
        WriteFile(hStdIn_Write,Cmd,sizeof(Cmd),&dwBytesToWrite,NULL);

    BOOL bSUCCESS =TRUE;
    Sleep(100);
    while(bSUCCESS)
    {

        BOOL bResult  = ReadFile(hStdOut_Read,Buff,70,&dwBytesReadFrom,NULL);
        if(!bResult)
        {
            break;
        }
        Buff[dwBytesReadFrom]=0;
        str+= Buff;
        bSUCCESS = dwBytesReadFrom!=0;
    }
    m_Disp = str;
    UpdateData(FALSE);
    CloseHandle(hStdIn_Read);
    CloseHandle(hStdIn_Write);
    CloseHandle(hStdOut_Read);
    CloseHandle(hStdOut_Write);
}

在上面的代码中,在调试模式下,第一次调用ReadFile函数返回 真实数据,但最后一次调用它会阻塞,因为没有足够的数据可供读取。

这是我的问题: 如何避免阻塞模式或获取读取的确切字节数?

问候!

1 个答案:

答案 0 :(得分:1)

您可能希望使用PeekNamedPipe函数,该函数允许您查询管道以查看在任何给定时间可用的数据量。如果lpBufferNULL,则不会读取任何数据。