在 Win32 C++桌面应用程序中读取进程的"标准输出"输出



我启动了一个Visual C++桌面应用程序(win32(,并创建了一个按钮,用于创建一个进程。

这是按钮代码:

INT_PTR CALLBACK Btn_Click(HWND hWnd)
{
wchar_t cmd[] = L"cmd.exe /c testprogram.exe";
STARTUPINFOW startInf;
memset(&startInf, 0, sizeof startInf);
PROCESS_INFORMATION procInf;
memset(&procInf, 0, sizeof procInf);
BOOL p = CreateProcess(NULL, cmd, NULL, NULL, TRUE,
CREATE_NO_WINDOW, NULL, NULL, &startInf, &procInf);
if (p)
{
CloseHandle(procInf.hProcess);
CloseHandle(procInf.hThread);
}
return TRUE;
}

我想在进程"运行"时读取进程的stdout输出(cmd.exe或testprogram.exe(,并将其设置为字符串。设置创建的文本输入的内容后。

我尝试了这个答案,但它冻结了应用程序。(因为ReadFile((和while((循环(

如何使用CreateProcess((和CreatePipe((读取cmd.exe的输出

我在论坛上搜索了更好的答案,但每个例子都是针对控制台应用程序的。

更新:我可以读取ping.exe的输出,但窗口保持冻结状态,直到ping.exe关闭。for((循环(和ReadFile(((会阻塞窗口。

wchar_t command[] = L"ping localhost";
STARTUPINFOW startInf;
memset(&startInf, 0, sizeof startInf);
PROCESS_INFORMATION procInf;
memset(&procInf, 0, sizeof procInf);
HANDLE cout_r = NULL;
HANDLE cout_w = NULL;
SECURITY_ATTRIBUTES sec_a;
//memset(&sec_a, 1, sizeof sec_a);
sec_a.nLength = sizeof(SECURITY_ATTRIBUTES);
sec_a.lpSecurityDescriptor = NULL;
CreatePipe(&cout_r, &cout_w, &sec_a, 0);
SetHandleInformation(cout_r, HANDLE_FLAG_INHERIT, 0);
//startInf.cb = sizeof(STARTUPINFO);
startInf.hStdOutput = cout_w;
startInf.dwFlags |= STARTF_USESTDHANDLES;

BOOL p = CreateProcess(NULL, command, NULL, NULL, TRUE,
NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, NULL, NULL, 
&startInf, &procInf);
if (p)
{
CloseHandle(procInf.hProcess);
CloseHandle(procInf.hThread);
CloseHandle(cout_w);
}
else
{
SetWindowTextA(hedit, "Failed");
}
char buf[1024];
CHAR chBuf[4096];
DWORD dwRead;
for (;;)
{
BOOL bSuccess = ReadFile(cout_r, chBuf, 4096, &dwRead, NULL);
if (!bSuccess || dwRead == 0) break;
std::string s(chBuf, dwRead);
std::wstring stemp = std::wstring(s.begin(), s.end());
OutputDebugStringW(stemp.c_str());
}

我在ReadFile和管道上搜索异步I/O。如果有人能给我提供一个关于如何在没有for((循环的情况下进行异步Readfile的例子,那就太好了。

如果UI线程停止发送消息,Windows将其视为冻结。这意味着您不应该在此线程上执行阻塞I/O。

您可以在ReadFile中使用异步(重叠(I/O,但在另一个线程中执行整个子进程操作要容易得多。按下按钮将启动线程,一旦线程读取了stdout,它就可以通过发送WM_APP消息向主窗口发出信号。

最新更新