例如有个控制台程序a打印出结果是Hello World
在我的程序里如何捕获这个Hello World?
在我的程序里如何捕获这个Hello World?
解决方案 »
- volatile类型变量问题
- 重叠IO时候的几个疑问
- ShellExecute的问题
- 注册表中,TypeLib 子键下的字符串是什么?
- 信息咨询
- 在sql2000个人版中,企业管理器中选定一个数据库,通过"所有任务",在选backup database,restore database可以实现备份,还原数据库.能否不通
- 高分求救::线程中传递参数问题!!!!!!!
- 谁比较清楚这个编译错误 Error C1067?
- 知道窗口类名,怎么样能查到该类的所有窗口?
- 如何才能让对话框具有WS_EX_TOPMOST风格;如何让对话框重载PreCreateWindow函数,好像不执行!!
- 在win2000下,有GetModuleFileNameEx可以从进程句柄得到文件名,在98下没有这个函数,有什么办法吗?
- 今天下午网易对孙大午的采访实录!!
感谢大家,我的问题解决了,不敢独享,放出来大家看看:
http://www.vchelp.net/vchelp/file2003_3/console.zip
接收输入输出的功能用Pipe技术在一个由CEditView类派生来的CconsoleView类实现实现。重要的成员函数有:1.重定向子进程的输入输出:BOOL CConsoleView::CreateConsoleRedirect(){ SECURITY_ATTRIBUTES saAttr; BOOL fSuccess; // Set the bInheritHandle flag so pipe handles are inherited. saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; // 重定向子进程的标准输出... // 保存当前标准输出的句柄 hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE); //为子进程的标准输出创建一个管道 if( !CreatePipe( &hChildStdoutRd, &hChildStdoutWr, &saAttr, 0) ) { TRACE0( _T("Stdout pipe creation failed\n") ); return FALSE; } // 设置一个写句柄到管道,使之成为标准输出 if( !SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr) ) { TRACE0( _T("Redirecting STDOUT failed\n") ); return FALSE; } // 创建不可继承的读句柄并关闭可继承的读句柄 fSuccess = DuplicateHandle( GetCurrentProcess(), hChildStdoutRd, GetCurrentProcess(), &hChildStdoutRdDup , 0, FALSE, DUPLICATE_SAME_ACCESS ); if( !fSuccess ) { TRACE0( _T("DuplicateHandle failed\n") ); return FALSE; } CloseHandle( hChildStdoutRd ); // 重定向子进程的标准输入... // 保存当前标准输入的句柄 hSaveStdin = GetStdHandle(STD_INPUT_HANDLE); //为子进程的标准输入创建一个管道 if( !CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0) ) { TRACE0( _T("Stdin pipe creation failed\n") ); return FALSE; } // 设置一个写句柄到管道,使之成为标准输入 if( !SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd) ) { TRACE0( _T("Redirecting Stdin failed\n") ); return FALSE; } // 复制写句柄到管道,这样它就不可继承 // Duplicate the write handle to the pipe so it is not inherited. fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr, GetCurrentProcess(), &hChildStdinWrDup, 0, FALSE, // not inherited DUPLICATE_SAME_ACCESS ); if( !fSuccess ) { TRACE0( _T("DuplicateHandle failed\n") ); return FALSE; } CloseHandle(hChildStdinWr); // 创建子进程 if( !CreateChildProcess(dwProcessId) ) { TRACE0( _T("CreateChildProcess failed\n") ); return FALSE; } // 子进程创建完毕,重置系统标准输入输出 if( !SetStdHandle(STD_INPUT_HANDLE, hSaveStdin) ) { TRACE0( _T("Re-redirecting Stdin failed\n") ); return FALSE; } if( !SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout) ) { TRACE0( _T("Re-redirecting Stdout failed\n") ); return FALSE; } m_pReadThread = AfxBeginThread( (AFX_THREADPROC)ReadPipeThreadProc,(LPVOID)this ); if( !m_pReadThread ) { TRACE0( _T("Cannot start read-redirect thread!\n") ); return FALSE; } return TRUE;}2.创建子进程:BOOL CConsoleView::CreateChildProcess(DWORD& dwProcessId){ PROCESS_INFORMATION piProcInfo; STARTUPINFO siStartInfo; ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) ); siStartInfo.cb = sizeof(STARTUPINFO); siStartInfo.dwFlags = STARTF_USESTDHANDLES; siStartInfo.hStdInput = hChildStdinRd; siStartInfo.hStdOutput = hChildStdoutWr; siStartInfo.hStdError = hChildStdoutWr; TCHAR shellCmd[_MAX_PATH]; if( !GetEnvironmentVariable(_T("ComSpec"), shellCmd, _MAX_PATH) ) return FALSE;#ifdef _UNICODE _tcscat( shellCmd, _T(" /U") );#else _tcscat( shellCmd, _T(" /A") );#endif // 创建子进程 BOOL ret = CreateProcess( NULL, shellCmd, // applicatin name NULL, // process security attributes NULL, // primary thread security attributes TRUE, // handles are inherited DETACHED_PROCESS, // creation flags NULL, // use parent's environment NULL, // use parent's current directory &siStartInfo, // STARTUPINFO pointer &piProcInfo); // receives PROCESS_INFORMATION if( ret ) dwProcessId = piProcInfo.dwProcessId; return ret;}3.写入到管道:void CConsoleView::WriteToPipe( LPCTSTR line ){ DWORD dwWritten; WriteFile( hChildStdinWrDup, line, _tcslen(line)*sizeof(TCHAR), &dwWritten, NULL );}4.读管道线程函数:UINT CConsoleView::ReadPipeThreadProc( LPVOID pParam ){ DWORD dwRead; TCHAR chBuf[BUFSIZE]; CConsoleView* pView = (CConsoleView*)pParam; TRACE0( _T("ReadPipe Thread begin run\n") ); for( ;; ) { if( !ReadFile( pView->hChildStdoutRdDup, chBuf, BUFSIZE, &dwRead, NULL) || dwRead == 0) break; chBuf[dwRead/sizeof(TCHAR)] = _T('\0'); pView->AddTexts( chBuf ); pView->m_nLength = pView->GetEditCtrl().SendMessage( WM_GETTEXTLENGTH ); } CloseHandle( pView ->hChildStdinRd); CloseHandle( pView ->hChildStdoutWr); CloseHandle( pView ->hChildStdinWrDup ); CloseHandle( pView ->hChildStdoutRdDup ); pView->m_pReadThread = NULL; pView->dwProcessId = DWORD(-1); pView->PostMessage( WM_CLOSE ); return 1;}5.退出程序时清除进程、线程:void CConsoleView::OnDestroy() { if( dwProcessId!=DWORD(-1) ) { HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwProcessId ); if( hProcess ) { TerminateProcess( hProcess,0 ); CloseHandle( hProcess ); } } if( m_pReadThread ) { TerminateThread( m_pReadThread->m_hThread,0 ); delete m_pReadThread; } CEditView::OnDestroy();}事实上,这个程序非常简单,干净利落,关键之处就在于上述几个成员函数。具体代码请参阅附带工程文件。值得注意的是当输入DOS命令cls时,程序应当清除之前接收的文本,输入DOS命令exit时,退出程序。可能还有其它的DOS命令要特别应对,笔者没有细究。