例如有个控制台程序a打印出结果是Hello World
在我的程序里如何捕获这个Hello World?

解决方案 »

  1.   

    引用:
    感谢大家,我的问题解决了,不敢独享,放出来大家看看:
    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命令要特别应对,笔者没有细究。
      

  2.   

    这个程序基本上是抄MSDN的:)