从匿名管道

时间:2015-04-23 13:16:02

标签: c++ windows console

我正在尝试执行命令行程序并在Windows上使用C ++获取输出。我最初使用_popen()实现了这一点,但这会导致命令提示符窗口弹出如上所述herehere

因此我实现了this answerthis article的混合,但遇到了ReadFile()死锁的问题。在更多阅读之后,我添加了对PeakNamedPipe()的调用,这导致读取循环执行无限而不是死锁(与我想要的相反,我宁愿等待exe退出),这让我相信我只是错误地设置了它。

以下代码是从原始代码(名称等)

稍加编辑的
std::wstring args = "cmdApplication.exe with some args";
HANDLE readHandle;
HANDLE writeOutHandle;
HANDLE writeErrHandle;
HANDLE writeHandle;

if (!CreatePipe(&readHandle, &writeHandle, NULL, 0)) {
    return false;
}

DuplicateHandle(GetCurrentProcess(), writeHandle, GetCurrentProcess(), &writeOutHandle, 0, true, DUPLICATE_SAME_ACCESS);
DuplicateHandle(GetCurrentProcess(), writeHandle, GetCurrentProcess(), &writeErrHandle, 0, true, DUPLICATE_SAME_ACCESS);

PROCESS_INFORMATION processInfo; 
STARTUPINFO startupInfo;
BOOL success = FALSE; 

ZeroMemory( &processInfo, sizeof(PROCESS_INFORMATION) );

ZeroMemory( &startupInfo, sizeof(STARTUPINFO) );
startupInfo.cb = sizeof(STARTUPINFO); 
startupInfo.hStdError = writeErrHandle;
startupInfo.hStdOutput = writeOutHandle;
startupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
startupInfo.dwFlags |= STARTF_USESTDHANDLES;

success = CreateProcess(NULL, (LPWSTR)args.c_str(), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &startupInfo, &processInfo);

DWORD read; 
CHAR buffer[4096];

while(true) {
    success = ReadFile(writeOutHandle, buffer, 4096, &read, NULL);//return false, GetLastError() returns ERROR_BROKEN_PIPE
    if( ! success || read == 0 ) break;
}

CloseHandle(readHandle);

//Deal with the data in buffer

我可以运行这样的命令行应用程序,或者我应该运行cmd.exe并使用和输入管道来提供args?我实际上是否正确设置了管道?

编辑:在评论中来回一些之后,ReadFile()不再死锁(保持写句柄阻止孩子完全退出)但不幸的是返回false,错误109: ERROR_BROKEN_PIPE很可能与this article有关(参见下文施法)。

  

如果正在使用匿名管道并且写入句柄已关闭,则当ReadFile尝试使用管道的相应读取句柄读取时,该函数返回FALSE,GetLastError返回ERROR_BROKEN_PIPE。

这引出了一个问题,如果我在管道打开时无法读取(由于ReadFile()阻塞)并且当它退出时我无法读取(因为我收到错误说管道已经结束) ),我如何从管道中读取?

0 个答案:

没有答案