我想在MFC编辑控件中显示命令行程序的标准输出。所以我通过AfxBeginThread
启动一个工作线程来通过PostMessage
更新UI(这部分工作得很好),工作线程通过管道与命令行子进程通信。但是我的工作线程无法读取管道中的任何内容(ReadFile
总是返回FALSE
),即使子进程退出,我的工作也无法退出。所以请帮助我。
这是我的代码。
创建子进程部分:
BOOL CMFCApplication3Dlg::execCmd(LPCSTR pCmdArg)
{
//ASSERT(s_hCmdProcess == NULL);
if (s_hCmdProcess != NULL)
{
return FALSE;
}
STARTUPINFO si; // specifies startup parameters for child process.
ZeroMemory(&si, sizeof(STARTUPINFO));
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; // STARTF_USESTDHANDLES is Required.
si.hStdOutput = s_cmdout_ChildSide; // Requires STARTF_USESTDHANDLES in dwFlags.
si.hStdError = s_cmdout_ChildSide; // Requires STARTF_USESTDHANDLES in dwFlags.
// si.hStdInput remains null.
si.wShowWindow = SW_HIDE; // Prevents cmd window from flashing. Requires STARTF_USESHOWWINDOW in dwFlags.
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
// Create the child process.
BOOL result = CreateProcess(
NULL,
(LPSTR)pCmdArg, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // TRUE=handles are inherited. Required.
CREATE_NEW_CONSOLE, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&si, // __in, STARTUPINFO pointer
&pi); // __out, receives PROCESS_INFORMATION
if (result)
{
s_hCmdProcess = pi.hProcess;
s_hCmdProcessThread = pi.hThread;
}
return result;
}
创建管道部分:
LRESULT CMFCApplication3Dlg::createPipe()
{
ASSERT(s_cmdout_ChildSide == NULL && s_cmdout_MainSide == NULL);
if (s_cmdout_ChildSide != NULL || s_cmdout_MainSide != NULL) return FALSE;
SECURITY_ATTRIBUTES saAttr = { sizeof(SECURITY_ATTRIBUTES) };
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
return CreatePipe(&s_cmdout_MainSide, &s_cmdout_ChildSide, &saAttr, 0);
}
工作线程部分:
void CMFCApplication3Dlg::startWorkThread()
{
if (s_hThread == NULL)
{
if (s_hThreadEvent != NULL) CloseHandle(s_hThreadEvent);
s_hThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
//s_hThread = AfxBeginThread(TestThreadProc, this);
s_hThread = AfxBeginThread(ReadCmdOutProc, this);
}
}
UINT ReadCmdOutProc(LPVOID pParam)
{
CWnd *hDlg = (CWnd *)pParam;
//start the child process
BOOL result = CMFCApplication3Dlg::execCmd("ping 127.0.0.1 -n 99");
ASSERT(CMFCApplication3Dlg::s_hCmdProcess != NULL);
for(;;)
{
DWORD dwRetVal_cmd;
//wait for child process quit.
dwRetVal_cmd = WaitForSingleObject(CMFCApplication3Dlg::s_hCmdProcess,100);
DWORD dwRead = 0;
CHAR chBuf[4096];
BOOL readResult = ReadFile(CMFCApplication3Dlg::s_cmdout_MainSide, chBuf, 4096, &dwRead, NULL);
if (readResult)
{
chBuf[dwRead] = 0;
TRACE("read: %s\n",chBuf);
CString* cmdread = new CString(chBuf, dwRead);
//send ui thread update message.
MsgWrapper::Post(hDlg, WM_APP + 11, (WPARAM)cmdread);
}
if (dwRetVal_cmd != WAIT_TIMEOUT)
{
TRACE("thread quit\n");
//release the resource
CMFCApplication3Dlg::releaseCmd();
GetExitCodeThread(CMFCApplication3Dlg::s_hThread, &dwExitCode);
AfxEndThread(dwExitCode);
CMFCApplication3Dlg::s_hThread = NULL;
break;
}
}
}