如何获取WinExec()及CreateProcess()函数运行时CMD命令窗口(或DOS命令窗口)的内容(CString)?例如在VC程序中通过WinExec()函数运行一个.BAT文件,如何获取CMD窗口出现的内容?。

解决方案 »

  1.   

    一个变通的办法是把dos窗口的输出重定向到一个文件里面,然后去读取,更好的方法是建立一个管道,
    你可以参考这个
    http://www.codeguru.com/misc/RedirectOutputToPipe.shtml
      

  2.   

    BOOL CShellView::CreateShellRedirect()
    {
    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;// The steps for redirecting child process's STDOUT:
    // 1. Save current STDOUT, to be restored later.
    // 2. Create anonymous pipe to be STDOUT for child process.
    // 3. Set STDOUT of the parent process to be write handle to
    // the pipe, so it is inherited by the child process.
    // 4. Create a noninheritable duplicate of the read handle and
    // close the inheritable read handle.// Save the handle to the current STDOUT.
    hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);// Create a pipe for the child process's STDOUT.
    if( !CreatePipe( &hChildStdoutRd, &hChildStdoutWr, &saAttr, 0) )
    {
    TRACE0( _T("Stdout pipe creation failed\n") );
    return FALSE;
    }// Set a write handle to the pipe to be STDOUT.
    if( !SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr) )
    {
    TRACE0( _T("Redirecting STDOUT failed\n") );
    return FALSE;
    }// Create noninheritable read handle and close the inheritable read handle.
    fSuccess = DuplicateHandle( GetCurrentProcess(), hChildStdoutRd,
    GetCurrentProcess(), &hChildStdoutRdDup ,
    0, FALSE,
    DUPLICATE_SAME_ACCESS );
    if( !fSuccess )
    {
    TRACE0( _T("DuplicateHandle failed\n") );
    return FALSE;
    }
    CloseHandle( hChildStdoutRd );// The steps for redirecting child process's STDIN:
    // 1. Save current STDIN, to be restored later.
    // 2. Create anonymous pipe to be STDIN for child process.
    // 3. Set STDIN of the parent to be the read handle to the
    // pipe, so it is inherited by the child process.
    // 4. Create a noninheritable duplicate of the write handle,
    // and close the inheritable write handle.// Save the handle to the current STDIN.
    hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);// Create a pipe for the child process's STDIN.
    if( !CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0) )
    {
    TRACE0( _T("Stdin pipe creation failed\n") );
    return FALSE;
    }
    // Set a read handle to the pipe to be STDIN.
    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);// Now create the child process.
    if( !CreateChildProcess(dwProcessId) )
    {
    TRACE0( _T("CreateChildProcess failed\n") );
    return FALSE;
    }
    // After process creation, restore the saved STDIN and STDOUT.
    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 =
    fxBeginThread( (AFX_THREADPROC)ReadPipeThreadProc,(LPVOID)this );
    if( !m_pReadThread )
    {
    TRACE0( _T("Cannot start read-redirect thread!\n") );
    return FALSE;
    }
    return TRUE;
    }BOOL CShellView::CreateChildProcess(DWORD& dwProcessId)
    {
    PROCESS_INFORMATION piProcInfo;
    STARTUPINFO siStartInfo;// Set up members of STARTUPINFO structure.
    ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
    siStartInfo.cb = sizeof(STARTUPINFO);
    /////////////////////////////////////////
    /*
    Note here the
    dwFlags should be STARTF_USESTDHANDLES, which is descripted in WIN32 API
    document, but this was
    omitted in MSDN sample
    */
    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
    // Create the child process.
    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.   

    我用上述方法并定义了一个ReadPipeThreadProc()处理函数,但不知如何打开一个.BAT文件及DOS窗口并获取DOS窗口数据?
      

  4.   

    利用重定向如you.bat>ddd.txt
    无法获取所有的窗口内容!