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不会在您的情况下退出匿名管道不支持异步(重叠)读写操作。-这是完全错误的。管道当然支持异步模式。管道是否有名称或为空-不影响这一点。更正确的说法是,通过具体apiCreatePipe
创建的管道是同步的TerminateProcess
-当然是错误的,不需要调用。这意味着您不能对匿名管道使用ReadFileEx
函数。此外,当这些函数与匿名管道一起使用时,ReadFile
的lpOverlapped参数被忽略。不,您搞错了。这可以创建异步匿名管道。只需使用另一个api,而不是CreatePipe
。当您说ReadFile的lpOverlapped参数被忽略时,您也会犯错误——即使对于同步文件,它也不会被忽略。当然,ReadFileEx也可以用于同步文件,所以您所说的一切都是错误的:1。ReadFile的lpOverlapped参数从未被忽略。对于任何文件模式。2ReadFileEx
可以始终使用,即使是同步文件。3.匿名管道不是某些特殊管道类型-仅存在管道和所有管道。哪个名称有管道(特殊情况下为空名称)-这不会影响同步或异步io模式关于ReadFileEx
-它不能仅用于绑定到iocp端口的文件,因为匿名管道不支持apc proc和iocp互斥同步(重叠)读写操作。-这是完全错误的。管道当然支持异步模式。管道是否有名称或为空-不影响这一点。更正确的说法是,通过具体apiCreatePipe
创建的管道是同步的TerminateProcess
-当然是错误的,不需要调用。这意味着您不能对匿名管道使用ReadFileEx
函数。此外,当这些函数与匿名管道一起使用时,ReadFile
的lpOverlapped参数被忽略。不,您搞错了。这可以创建异步匿名管道。只需使用另一个api,而不是CreatePipe
。当您说ReadFile的lpOverlapped参数被忽略时,您也会犯错误——即使对于同步文件,它也不会被忽略。当然,ReadFileEx也可以用于同步文件,所以您所说的一切都是错误的:1。ReadFile的lpOverlapped参数从未被忽略。对于任何文件模式。2ReadFileEx
可以始终使用,即使是同步文件。3.匿名管道不是某些特殊管道类型-存在于