我在程序中用CreateProcess()执行一个DOS程序,这个DOS程序有屏幕输出,为此,我先用CreatePipe()创建了一个管道,在CreateProcess()函数中设置屏幕(标准)输出重定向到刚创建的管道。
为了读取管道内的数据,我用CreateThrea()创建了一个线程,并向这个线程过程传递一个管道的“读句柄”。
问题:
1 代码如何组织?
2 DOS程序结束了,线程还在不停的读,如何判断DOS程序结束,又如何让线程停下来?

解决方案 »

  1.   

    前些天刚写过这种代码,贴出部分,供你参考
    DWORD WINAPI RunWritePipeThread(PVOID wParam)
    {
    DWORD dwRead;
    CDataStream* pHandle = (CDataStream*)wParam;
    char temp[400];
    memset(temp, '\0', 400);

    TRACE0( _T("ReadPipe Thread begin run\n") );
    int len = 0;
    memset(pHandle->chBuf, '\0', 4096);
    for( ;; )    

    memset(temp, '\0', 400);
    if( !ReadFile(pHandle->hChildStdoutRdDup, temp, 
    400, &dwRead, NULL) || dwRead == 0) 
    {
    break;
    }

                      if((len + dwRead) > 4096)
    {
    break;
    }
    memcpy(pHandle->chBuf + len, temp, dwRead);
    len = len + dwRead;
    }  CloseHandle( pHandle->hChildStdinRd);
    CloseHandle( pHandle->hChildStdoutWr);
    CloseHandle( pHandle->hChildStdinWrDup );
    CloseHandle( pHandle->hChildStdoutRdDup );

             pHandle->dwProcessId = DWORD(-1);
    return 0;
    }BOOL CDataStream::CreateChildProcess(DWORD &dwProcessId, const char* arg)
    {
    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;
    int len = strlen(arg);

    CString strCommand = _T("d:\\DataStream.exe");

    BOOL ret = CreateProcess(NULL, strCommand.GetBuffer(), NULL, NULL,TRUE,DETACHED_PROCESS,NULL,NULL,&siStartInfo,&piProcInfo);
    if( ret )
        dwProcessId = piProcInfo.dwProcessId;
    return ret;
    }BOOL CDataStream::LogOpt(const char *arg)
    {
    SECURITY_ATTRIBUTES saAttr;
    BOOL fSuccess; 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;
    }
    // 复制写句柄到管道,这样它就不可继承
    fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr, 
    GetCurrentProcess(), &hChildStdinWrDup, 
    0, FALSE,                  // not inherited       
    DUPLICATE_SAME_ACCESS ); 
    if( !fSuccess ) 
    {
    TRACE0( _T("DuplicateHandle failed\n") );
    return false;
    }

    CloseHandle(hChildStdinWr);  
    AfxBeginThread( (AFX_THREADPROC)RunWritePipeThread,(LPVOID)this );

    Sleep(10);
    if(CreateChildProcess(dwProcessId, arg))
    {
    return true;
    }

    return false;
    }