Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.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++ 管道读取时挂起的ReadFile_C++_Winapi - Fatal编程技术网

C++ 管道读取时挂起的ReadFile

C++ 管道读取时挂起的ReadFile,c++,winapi,C++,Winapi,我正在使用CreateProcess()运行cmd.exe(没有向用户显示物理窗口)并需要处理输出。为此,我决定使用CreatePipe() 我目前遇到一个问题,所有输出都被读取和处理,但对ReadFile()的最后一个调用挂起。四处搜索告诉我在阅读之前需要关闭管道的写入端,这是解决此问题的方法,但我已经这样做了,仍然存在此问题 这是我的密码: // sw -> path to cmd.exe, ptr is the command ok = CreateProcess(sw, ptr,

我正在使用
CreateProcess()
运行
cmd.exe
(没有向用户显示物理窗口)并需要处理输出。为此,我决定使用
CreatePipe()

我目前遇到一个问题,所有输出都被读取和处理,但对
ReadFile()
的最后一个调用挂起。四处搜索告诉我在阅读之前需要关闭管道的写入端,这是解决此问题的方法,但我已经这样做了,仍然存在此问题

这是我的密码:

// sw -> path to cmd.exe, ptr is the command
ok = CreateProcess(sw, ptr, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &StartupInfo, &ProcessInfo);
CloseHandle(hStdInPipeRead);
char buf[1024 + 1] = {};
DWORD dwRead = 0;
DWORD dwAvailable = 0;
DWORD testRes;
CloseHandle(hStdOutPipeWrite);
ok = ReadFile(hStdOutPipeRead, buf, 1024, &dwRead, NULL);
// String handling for initial read omitted for clarity
string temp = buf;
bool holdOff = false;

while (ok == TRUE)
{
    buf[dwRead] = '\0';
    OutputDebugStringA(buf);
    puts(buf);
    // ReadFile gets all the correct output from cmd here but it also hangs on the very last call. How to fix?
    ok = ReadFile(hStdOutPipeRead, buf, 1024, &dwRead, NULL);
    temp = buf;
    // handle and store output
    break;
}
CloseHandle(hStdOutPipeRead);
CloseHandle(hStdInPipeWrite);

如果您设置了
SECURITY\u ATTRIBUTES.bInheritHandle=true
,则子进程将继承管道的句柄,您关闭的管道的写入句柄只是父进程的,子进程中仍有一个句柄(子进程的stdout),并且在cihld进程中尚未关闭,
Readfile
失败,仅当所有写入句柄关闭或出现错误时才会返回

另外,

不支持异步(重叠)读写操作 通过匿名管道(通过
CreatePipe
创建)

所以,若您仍然需要向子进程发送命令来执行cmd,那个么您应该将
ReadFile
放在一个线程中。 如果不再需要,请终止子进程:

TerminateProcess(ProcessInfo.hProcess,0);
WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
ok = ReadFile(hStdOutPipeRead, buf, 1024, &dwRead, NULL);
// String handling for initial read omitted for clarity
string temp = buf;
bool holdOff = false;
while (ok == TRUE)
{
    buf[dwRead] = '\0';
    OutputDebugStringA(buf);
    puts(buf);
    // ReadFile gets all the correct output from cmd here but it also hangs on the very last call. How to fix?
    ok = ReadFile(hStdOutPipeRead, buf, 1024, &dwRead, NULL);
    temp = buf;
    // handle and store output
    break;
}
CloseHandle(hStdOutPipeRead);
CloseHandle(hStdInPipeWrite);

如果您设置了
SECURITY\u ATTRIBUTES.bInheritHandle=true
,则子进程将继承管道的句柄,您关闭的管道的写入句柄只是父进程的,子进程中仍有一个句柄(子进程的stdout),并且在cihld进程中尚未关闭,
Readfile
失败,仅当所有写入句柄关闭或出现错误时才会返回

另外,

不支持异步(重叠)读写操作 通过匿名管道(通过
CreatePipe
创建)

所以,若您仍然需要向子进程发送命令来执行cmd,那个么您应该将
ReadFile
放在一个线程中。 如果不再需要,请终止子进程:

TerminateProcess(ProcessInfo.hProcess,0);
WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
ok = ReadFile(hStdOutPipeRead, buf, 1024, &dwRead, NULL);
// String handling for initial read omitted for clarity
string temp = buf;
bool holdOff = false;
while (ok == TRUE)
{
    buf[dwRead] = '\0';
    OutputDebugStringA(buf);
    puts(buf);
    // ReadFile gets all the correct output from cmd here but it also hangs on the very last call. How to fix?
    ok = ReadFile(hStdOutPipeRead, buf, 1024, &dwRead, NULL);
    temp = buf;
    // handle and store output
    break;
}
CloseHandle(hStdOutPipeRead);
CloseHandle(hStdInPipeWrite);


没有
sw
ptr
值,很难推断
cmd
的作用。在退出
cmd
之前,您的管道是有效的。对于什么,您创建了2对管道(4个句柄),而不是1对管道(2个句柄)?从self-side使用异步管道端点您没有显示设置管道或CreateProcess参数的代码。请提供一个。@RemyLebeau-可以假定这是一般的复制粘贴,并且需要理解-只有当另一端的所有句柄都将关闭时,readfile才会失败(带有
错误\u断开的\u管道
)。因为这需要关闭
hStdOutPipeWrite
,当cmd退出时,复制的句柄将被关闭。因此,在没有
sw
ptr
值的情况下,cmd不会退出。很难推断
cmd
的作用。在退出
cmd
之前,您的管道是有效的。对于什么,您创建了2对管道(4个句柄),而不是1对管道(2个句柄)?从self-side使用异步管道端点您没有显示设置管道或CreateProcess参数的代码。请提供一个。@RemyLebeau-可以假定这是一般的复制粘贴,并且需要理解-只有当另一端的所有句柄都将关闭时,readfile才会失败(带有
错误\u断开的\u管道
)。因为这需要关闭
hStdOutPipeWrite
,当cmd退出时,复制的句柄将被关闭。因此,cmd不会在您的情况下退出匿名管道不支持异步(重叠)读写操作。-这是完全错误的。管道当然支持异步模式。管道是否有名称或为空-不影响这一点。更正确的说法是,通过具体api
CreatePipe
创建的管道是同步的
TerminateProcess
-当然是错误的,不需要调用。这意味着您不能对匿名管道使用
ReadFileEx
函数。此外,当这些函数与匿名管道一起使用时,
ReadFile
的lpOverlapped参数被忽略。不,您搞错了。这可以创建异步匿名管道。只需使用另一个api,而不是
CreatePipe
。当您说ReadFile的lpOverlapped参数被忽略时,您也会犯错误——即使对于同步文件,它也不会被忽略。当然,ReadFileEx也可以用于同步文件,所以您所说的一切都是错误的:1。ReadFile的lpOverlapped参数从未被忽略。对于任何文件模式。2
ReadFileEx
可以始终使用,即使是同步文件。3.匿名管道不是某些特殊管道类型-仅存在管道和所有管道。哪个名称有管道(特殊情况下为空名称)-这不会影响同步或异步io模式关于
ReadFileEx
-它不能仅用于绑定到iocp端口的文件,因为匿名管道不支持apc proc和iocp互斥同步(重叠)读写操作。-这是完全错误的。管道当然支持异步模式。管道是否有名称或为空-不影响这一点。更正确的说法是,通过具体api
CreatePipe
创建的管道是同步的
TerminateProcess
-当然是错误的,不需要调用。这意味着您不能对匿名管道使用
ReadFileEx
函数。此外,当这些函数与匿名管道一起使用时,
ReadFile
的lpOverlapped参数被忽略。不,您搞错了。这可以创建异步匿名管道。只需使用另一个api,而不是
CreatePipe
。当您说ReadFile的lpOverlapped参数被忽略时,您也会犯错误——即使对于同步文件,它也不会被忽略。当然,ReadFileEx也可以用于同步文件,所以您所说的一切都是错误的:1。ReadFile的lpOverlapped参数从未被忽略。对于任何文件模式。2
ReadFileEx
可以始终使用,即使是同步文件。3.匿名管道不是某些特殊管道类型-存在于