Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Win32 ReadFile输出,无需等待缓冲区_C++_Visual Studio 2012_Readfile - Fatal编程技术网

C++ Win32 ReadFile输出,无需等待缓冲区

C++ Win32 ReadFile输出,无需等待缓冲区,c++,visual-studio-2012,readfile,C++,Visual Studio 2012,Readfile,我使用CreateProcess()运行cmd.exe命令。命令本身有一个无止境的输出,所以我使用一个我从中修改的函数将部分输出转换成字符串 #define BUFSIZE 4096 HANDLE g_hChildStd_OUT_Rd = NULL; std::string ReadFromPipe(PROCESS_INFORMATION piProcInfo) { DWORD dwRead; CHAR chBuf[BUFSIZE]; ReadFile( g_hChi

我使用
CreateProcess()
运行cmd.exe命令。命令本身有一个无止境的输出,所以我使用一个我从中修改的函数将部分输出转换成字符串

#define BUFSIZE 4096
HANDLE g_hChildStd_OUT_Rd = NULL;

std::string ReadFromPipe(PROCESS_INFORMATION piProcInfo) {
    DWORD dwRead; 
    CHAR chBuf[BUFSIZE];
    ReadFile( g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL);
    std::string s(chBuf, dwRead);
    return s;
}
但是这段代码产生了一些问题

首先,每次我调用它时,它可能会在等待输出缓冲到4096字节时冻结程序

其次,它总是只获取输出队列中的下一个4096字节。(即使电流输出大得多)

我想要的是调用函数,同时获取输出的所有数据,并且能够设置要获取的最小字节数(而不是缓冲区)。如果最小字节数还不可用,我希望它完全跳过
ReadFile()
,只返回
false
。(而不是冻结应用程序)


这可能吗?

一个选项是将从管道读取的代码放在自己的线程中,并使其在循环中运行。这将防止主线程阻塞,并且您始终可以读取尽可能多的数据。挑战在于,您现在需要有一种方法让读取线程将数据传输回主线程


另一种选择是使用重叠I/O,这在MSDN中的ReadFile和CreateFile文档中进行了讨论。这是一种在从管道读取数据时让操作系统回调的方法。因此,您的ReadFile不会被阻止,但(可能)在稍后之前缓冲区中不会有任何数据。

Arkadiy的评论将我引向了正确的方向。我是在
PeekNamedPipe()的帮助下完成的。

我当前的代码:

#include <string>
#include <iostream>
#include <windows.h> 
#include <stdio.h>

#pragma warning( disable : 4800 ) // hide bool warning
#define BUFSIZE 1024
HANDLE g_hChildStd_OUT_Rd = NULL;

std::string ReadFromPipe(PROCESS_INFORMATION piProcInfo) {
    CHAR chBuf[BUFSIZE];
    DWORD dwRead;
    DWORD avail;
    bool bSuccess = FALSE;
    bool tSuccess = FALSE;
    std::string out = "";
    tSuccess = PeekNamedPipe( g_hChildStd_OUT_Rd, NULL, 0, NULL, &avail, NULL );
    if (tSuccess && avail >= BUFSIZE) {
        while (avail >= BUFSIZE) {
            bSuccess=ReadFile( g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL);
            if( ! bSuccess || dwRead == 0 ) break; 
            std::string s(chBuf, dwRead);
            out += s;
            avail = avail - BUFSIZE;
        }
        return out;
    } else {
        return "[false]";
    }
}
#包括
#包括
#包括
#包括
#杂注警告(禁用:4800)//隐藏布尔警告
#定义bufsize1024
HANDLE g_hChildStd_OUT_Rd=NULL;
std::string ReadFromPipe(进程信息piProcInfo){
CHAR chBuf[BUFSIZE];
德沃德·德雷德;
德沃德·艾维尔;
bool bsucces=假;
bool-tsucess=FALSE;
std::string out=“”;
tsaccess=PeekNamedPipe(g_hchildsd_OUT_Rd,NULL,0,NULL,&avail,NULL);
if(tsucess&&avail>=BUFSIZE){
while(avail>=BUFSIZE){
bSuccess=ReadFile(g_hchildsd_OUT_Rd,chBuf,BUFSIZE,&dwRead,NULL);
如果(!bsucces | | dwRead==0)中断;
std::字符串s(chBuf,dwRead);
out+=s;
avail=avail-BUFSIZE;
}
返回;
}否则{
返回“[假]”;
}
}

调用此函数时,将返回自上次调用以来的输出
BUFSIZE
现在充当最小缓冲区,如果输出小于最小缓冲区,函数将返回
[false]
(作为字符串,而不是bool)。

试试这个:很棒的链接。谢谢。:)它不应该等待所有4096字节。它应该在至少有一个字节可用时返回。你确定这个问题真的存在吗?NB您必须检查错误返回。这可能是因为我正在构建一个FielSoess项目,我正在从浏览器调用C++函数,所以它也会冻结,因为浏览器不能返回到返回值。但是我确信函数会一直等到得到整个缓冲区,然后才返回值。我的回答完全解决了这个问题。