在 Win32 C++ 桌面应用程序中读取进程的 'stdout' 输出
Read process's 'stdout' output in Win32 C++ Desktop Application
我启动了一个 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;
}
我想在它是 'running' 时读取进程的标准输出输出(cmd.exe 或 testprogram.exe)并将其设置为字符串。设置创建的文本输入的内容后。
我试过这个答案,但它冻结了应用程序。 (因为 ReadFile() 和 while() 循环)
How to read output from cmd.exe using CreateProcess() and CreatePipe()
我在论坛上搜索了一个更好的答案,但每个示例都是针对控制台应用程序的。
更新:
我可以读取 ping.exe 的输出,但 window 保持冻结状态,直到 ping.exe 关闭。 for() 循环(和 ReadFile())阻塞了 window .
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。
您可以将异步(重叠)I/O 与 ReadFile 一起使用,但在另一个线程中执行整个子进程操作要容易得多。按下按钮将启动线程,一旦线程读取了标准输出,它就可以通过发送 WM_APP 消息向主 window 发信号。
我启动了一个 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;
}
我想在它是 'running' 时读取进程的标准输出输出(cmd.exe 或 testprogram.exe)并将其设置为字符串。设置创建的文本输入的内容后。
我试过这个答案,但它冻结了应用程序。 (因为 ReadFile() 和 while() 循环)
How to read output from cmd.exe using CreateProcess() and CreatePipe()
我在论坛上搜索了一个更好的答案,但每个示例都是针对控制台应用程序的。
更新: 我可以读取 ping.exe 的输出,但 window 保持冻结状态,直到 ping.exe 关闭。 for() 循环(和 ReadFile())阻塞了 window .
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。
您可以将异步(重叠)I/O 与 ReadFile 一起使用,但在另一个线程中执行整个子进程操作要容易得多。按下按钮将启动线程,一旦线程读取了标准输出,它就可以通过发送 WM_APP 消息向主 window 发信号。