感谢大侠detrox的代码,实现管道的读出没有问题,代码在http://dev.csdn.net/develop/article/18/18338.shtm 。
但是如何实现管道的读出呢,比如,创进一个 cmd.exe 进程后,向其写入多行命令,如何实现?我用如下代码:
//创建单个进程,通过管道写入命令
SECURITY_ATTRIBUTES sat = {0};
sat.nLength = sizeof( SECURITY_ATTRIBUTES );
sat.lpSecurityDescriptor = NULL;
sat.bInheritHandle = TRUE;
HANDLE hPipeRead=NULL, hPipeWrite=NULL; 
BOOL bPipeOk = CreatePipe( &hPipeRead, &hPipeWrite, &sat, NULL );
if( !bPipeOk  )
{
return;
}
STARTUPINFO StartUpInfo = {0};
PROCESS_INFORMATION ProInfo = {0};
    StartUpInfo.cb = sizeof( StartUpInfo );
    StartUpInfo.lpReserved = NULL;
    StartUpInfo.dwFlags = 0;
    StartUpInfo.cbReserved2 = 0;
    StartUpInfo.lpReserved2 = NULL; 
    StartUpInfo.lpDesktop = NULL;
    StartUpInfo.lpTitle = NULL;
    StartUpInfo.dwX = 0;
    StartUpInfo.dwY = 0;
    StartUpInfo.dwXSize = 0;
    StartUpInfo.dwYSize = 0;
    StartUpInfo.dwXCountChars = 0;
    StartUpInfo.dwYCountChars = 0;
    StartUpInfo.dwFillAttribute = 0;
    StartUpInfo.dwFlags = NULL;//STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    StartUpInfo.wShowWindow = SW_HIDE;
    StartUpInfo.hStdInput = hPipeRead;
    StartUpInfo.hStdOutput = NULL;//hPipeWrite;
    StartUpInfo.hStdError = NULL;//hPipeWrite;
BOOL bProOk = CreateProcess( NULL, "cmd",
NULL, NULL, TRUE, NULL, NULL, NULL,
&StartUpInfo, &ProInfo );
if( !bProOk )
{
bProOk = CreateProcess( NULL, "command",
NULL, NULL, TRUE, NULL, NULL, NULL,
&StartUpInfo, &ProInfo );
}
if( !bProOk )
{
return;
}
CloseHandle( hPipeRead );

char szCmdLine[1024] = {0};
m_edit_command.GetWindowText( szCmdLine, 1020 );
strcat( szCmdLine, "\r\n" );
// 写入命令
ULONG uWrited = 0;
BOOL bWriteOk = WriteFile( hPipeWrite, szCmdLine, strlen(szCmdLine), &uWrited, NULL );
char szWrited[256] = {0};
sprintf( szWrited, "writed: %d", uWrited );
MessageBox( szWrited ); // 关闭进程
// TerminateProcess( ProInfo.hProcess, 0 );
CloseHandle( hPipeRead );
CloseHandle( hPipeWrite );
CloseHandle( ProInfo.hProcess); return;发现,WriteFile写入成功,但并未成功输入cmd窗口中。请大侠指教。

解决方案 »

  1.   

    AllocConsole();  
    HANDLE  hOutput=GetStdHandle(STD_OUTPUT_HANDLE);  
    unsigned  long  lgsize;  
    WriteFile(hOutput,strbuf,strlen(strbuf),&lgsize,0);  
    FreeConsole();
    PS:楼主的表述有点乱啊
      

  2.   

    输入到cmd窗口应该用:
    GetStdHandle
    ReadConsoleInput
    WriteConsoleInput
    WriteConsoleOutput
    等几个控制台API
      

  3.   

    谢谢laiyiling。请问一下,你的这段代码与我的代码中创建的线程是如何联系的?
      

  4.   

    修改这两行代码:
    StartUpInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    StartUpInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
      

  5.   

    谢谢orbit,我试一下。
    我是想向cmd进程写入命令,好象应该是设置 hStdInput 吧。
      

  6.   

    orbit,我试了,还是无效啊。
      

  7.   

    参考一下几个控制台API的使用吧:#include <windows.h> 
     
    void NewLine(void); 
    void ScrollScreenBuffer(HANDLE, INT); 
     
    HANDLE hStdout, hStdin; 
    CONSOLE_SCREEN_BUFFER_INFO csbiInfo; 
     
    void main(void) 

        LPSTR lpszPrompt1 = "Type a line and press Enter, or q to quit: ";
        LPSTR lpszPrompt2 = "Type any key, or q to quit: ";
        CHAR chBuffer[256]; 
        DWORD cRead, cWritten, fdwMode, fdwOldMode; 
        WORD wOldColorAttrs;     // Get handles to STDIN and STDOUT.     hStdin = GetStdHandle(STD_INPUT_HANDLE); 
        hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
        if (hStdin == INVALID_HANDLE_VALUE || 
            hStdout == INVALID_HANDLE_VALUE) 
        {
            MessageBox(NULL, "GetStdHandle", "Console Error", MB_OK);
            return;
        }    // Save the current text colors.     if (! GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) 
        {
            MessageBox(NULL, "GetConsoleScreenBufferInfo", 
                "Console Error", MB_OK); 
            return;
        }    wOldColorAttrs = csbiInfo.wAttributes;     // Set the text attributes to draw red text on black background.     if (! SetConsoleTextAttribute(hStdout, FOREGROUND_RED | 
                FOREGROUND_INTENSITY))
        {
            MessageBox(NULL, "SetConsoleTextAttribute", "Console Error", 
                MB_OK);
            return;
        }    // Write to STDOUT and read from STDIN by using the default 
        // modes. Input is echoed automatically, and ReadFile 
        // does not return until a carriage return is typed. 
        // 
        // The default input modes are line, processed, and echo. 
        // The default output modes are processed and wrap at EOL.     while (1) 
        { 
            if (! WriteFile( 
                hStdout,              // output handle 
                lpszPrompt1,          // prompt string 
                lstrlen(lpszPrompt1), // string length 
                &cWritten,            // bytes written 
                NULL) )               // not overlapped 
            {
                MessageBox(NULL, "WriteFile", "Console Error", MB_OK); 
                return;
            }        if (! ReadFile( 
                hStdin,    // input handle 
                chBuffer,  // buffer to read into 
                255,       // size of buffer 
                &cRead,    // actual bytes read 
                NULL) )    // not overlapped 
            break; 
            if (chBuffer[0] == 'q') break; 
        }     // Turn off the line input mode, and echo the input mode.     if (! GetConsoleMode(hStdin, &fdwOldMode)) 
        {
            MessageBox(NULL, "GetConsoleMode", "Console Error", MB_OK); 
            return;
        }    fdwMode = fdwOldMode & 
            ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT); 
        if (! SetConsoleMode(hStdin, fdwMode)) 
        {
            MessageBox(NULL, "SetConsoleMode", "Console Error", MB_OK); 
            return;
        }    // Without line and echo input modes, ReadFile returns 
        // when any input is available. Carriage returns must 
        // be handled, and WriteFile is used to echo input.     NewLine();    while (1) 
        { 
            if (! WriteFile( 
                hStdout,              // output handle 
                lpszPrompt2,          // prompt string 
                lstrlen(lpszPrompt2), // string length 
                &cWritten,            // bytes written 
                NULL) )               // not overlapped 
            {
                MessageBox(NULL, "WriteFile", "Console Error", MB_OK);
                return;
            }        if (! ReadFile(hStdin, chBuffer, 1, &cRead, NULL)) 
                break; 
            if (chBuffer[0] == '\r')
                NewLine();
            else if (! WriteFile(hStdout, chBuffer, cRead, 
                &cWritten, NULL)) break;
            else
                NewLine();
            if (chBuffer[0] == 'q') break; 
        }     // Restore the original console mode.     SetConsoleMode(hStdin, fdwOldMode);    // Restore the original text colors.     SetConsoleTextAttribute(hStdout, wOldColorAttrs);
    }// The NewLine function handles carriage returns when the processed 
    // input mode is disabled. It gets the current cursor position 
    // and resets it to the first cell of the next row. 
     
    void NewLine(void) 

        if (! GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) 
        {
            MessageBox(NULL, "GetConsoleScreenBufferInfo", 
                "Console Error", MB_OK); 
            return;
        }    csbiInfo.dwCursorPosition.X = 0;     // If it is the last line in the screen buffer, scroll 
        // the buffer up.     if ((csbiInfo.dwSize.Y-1) == csbiInfo.dwCursorPosition.Y) 
        { 
            ScrollScreenBuffer(hStdout, 1); 
        }     // Otherwise, advance the cursor to the next line.     else csbiInfo.dwCursorPosition.Y += 1; 
     
        if (! SetConsoleCursorPosition(hStdout, 
            csbiInfo.dwCursorPosition)) 
        {
            MessageBox(NULL, "SetConsoleCursorPosition", "Console Error", 
                MB_OK); 
            return;
        }
    } void ScrollScreenBuffer(HANDLE h, INT x)
    {
        SMALL_RECT srctScrollRect, srctClipRect;
        CHAR_INFO chiFill;
        COORD coordDest;    srctScrollRect.Left = 0;
        srctScrollRect.Top = 1;
        srctScrollRect.Right = csbiInfo.dwSize.X - x; 
        srctScrollRect.Bottom = csbiInfo.dwSize.Y - x; 
     
        // The destination for the scroll rectangle is one row up. 
     
        coordDest.X = 0; 
        coordDest.Y = 0; 
     
        // The clipping rectangle is the same as the scrolling rectangle. 
        // The destination row is left unchanged. 
     
        srctClipRect = srctScrollRect; 
     
        // Set the fill character and attributes. 
     
        chiFill.Attributes = FOREGROUND_RED|FOREGROUND_INTENSITY; 
        chiFill.Char.AsciiChar = (char)' '; 
     
        // Scroll up one line. 
     
        ScrollConsoleScreenBuffer( 
            h,               // screen buffer handle 
            &srctScrollRect, // scrolling rectangle 
            &srctClipRect,   // clipping rectangle 
            coordDest,       // top left destination cell 
            &chiFill);       // fill character and color 
    }
      

  8.   

    汗~参考一下将文件输入到产生的进程:
    #include <windows.h> 
    #include <stdio.h> 
     
    #define BUFSIZE 4096 
     
    HANDLE hChildStdinRd, hChildStdinWr,  
       hChildStdoutRd, hChildStdoutWr, 
       hInputFile, hStdout;
     
    BOOL CreateChildProcess(VOID); 
    VOID WriteToPipe(VOID); 
    VOID ReadFromPipe(VOID); 
    VOID ErrorExit(LPTSTR); 
    VOID ErrMsg(LPTSTR, BOOL); 
     
    DWORD main(int argc, char *argv[]) 

       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; // Get the handle to the current STDOUT. 
     
       hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
     
    // Create a pipe for the child process's STDOUT. 
     
       if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) 
          ErrorExit("Stdout pipe creation failed\n"); // Ensure the read handle to the pipe for STDOUT is not inherited.   SetHandleInformation( hChildStdoutRd, HANDLE_FLAG_INHERIT, 0);// Create a pipe for the child process's STDIN. 
     
       if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) 
          ErrorExit("Stdin pipe creation failed\n"); // Ensure the write handle to the pipe for STDIN is not inherited. 
     
       SetHandleInformation( hChildStdinWr, HANDLE_FLAG_INHERIT, 0);
     
    // Now create the child process. 
       
       fSuccess = CreateChildProcess();
       if (! fSuccess) 
          ErrorExit("Create process failed with"); // Get a handle to the parent's input file. 
     
       if (argc == 1) 
          ErrorExit("Please specify an input file");    printf( "Debug: argv[1] = %s\n", argv[1]);   hInputFile = CreateFile(argv[1], GENERIC_READ, 0, NULL, 
          OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);    if (hInputFile == INVALID_HANDLE_VALUE) 
          ErrorExit("CreateFile failed"); 
     
    // Write to pipe that is the standard input for a child process. 
     
       WriteToPipe(); 
     
    // Read from pipe that is the standard output for child process. 
     
       ReadFromPipe(); 
     
       return 0; 

     
    BOOL CreateChildProcess() 

       PROCESS_INFORMATION piProcInfo; 
       STARTUPINFO siStartInfo;
       BOOL bFuncRetn = FALSE; 
     
    // Set up members of the PROCESS_INFORMATION structure. 
     
       ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
     
    // Set up members of the STARTUPINFO structure. 
     
       ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
       siStartInfo.cb = sizeof(STARTUPINFO); 
       siStartInfo.hStdError = hChildStdoutWr;
       siStartInfo.hStdOutput = hChildStdoutWr;
       siStartInfo.hStdInput = hChildStdinRd;
       siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
     
    // Create the child process. 
        
       bFuncRetn = CreateProcess(NULL, 
          "cmd",       // command line 
          NULL,          // process security attributes 
          NULL,          // primary thread security attributes 
          TRUE,          // handles are inherited 
          0,             // creation flags 
          NULL,          // use parent's environment 
          NULL,          // use parent's current directory 
          &siStartInfo,  // STARTUPINFO pointer 
          &piProcInfo);  // receives PROCESS_INFORMATION 
       
       if (bFuncRetn == 0) 
          ErrorExit("CreateProcess failed\n");
       else 
       {
          CloseHandle(piProcInfo.hProcess);
          CloseHandle(piProcInfo.hThread);
          return bFuncRetn;
       }
    }
     
    VOID WriteToPipe(VOID) 

       DWORD dwRead, dwWritten; 
       CHAR chBuf[BUFSIZE]; 
     
    // Read from a file and write its contents to a pipe. 
     
       for (;;) 
       { 
          if (! ReadFile(hInputFile, chBuf, BUFSIZE, &dwRead, NULL) || 
             dwRead == 0) break; 
          if (! WriteFile(hChildStdinWr, chBuf, dwRead, 
             &dwWritten, NULL)) break; 
       } 
     
    // Close the pipe handle so the child process stops reading. 
     
       if (! CloseHandle(hChildStdinWr)) 
          ErrorExit("Close pipe failed\n"); 

     
    VOID ReadFromPipe(VOID) 

       DWORD dwRead, dwWritten; 
       CHAR chBuf[BUFSIZE]; // Close the write end of the pipe before reading from the 
    // read end of the pipe. 
     
       if (!CloseHandle(hChildStdoutWr)) 
          ErrorExit("Closing handle failed"); 
     
    // Read output from the child process, and write to parent's STDOUT. 
     
       for (;;) 
       { 
          if( !ReadFile( hChildStdoutRd, chBuf, BUFSIZE, &dwRead, 
             NULL) || dwRead == 0) break; 
          if (! WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL)) 
             break; 
       } 

     
    VOID ErrorExit (LPTSTR lpszMessage) 

       fprintf(stderr, "%s\n", lpszMessage); 
       ExitProcess(0); 
      

  9.   

    我试过了,还是不行。大侠能否看看我的这段代码有什么毛病,谢谢。
    (按下某按钮后执行“cmd”,然后写入“dir\r\n”命令,程序报告写入了5个字节,但是cmd窗口没反应)
    void CCmdPipeDlg::OnButtonDo() 
    {
    // TODO: Add your control notification handler code here
    //创建单个进程,通过管道写入命令
    SECURITY_ATTRIBUTES sat = {0};
    sat.nLength = sizeof( SECURITY_ATTRIBUTES );
    sat.lpSecurityDescriptor = NULL;
    sat.bInheritHandle = TRUE;
    HANDLE hPipeRead1=NULL, hPipeWrite1=NULL;
    HANDLE hPipeRead2=NULL, hPipeWrite2=NULL;
    BOOL bPipeOk1 = CreatePipe( &hPipeRead1, &hPipeWrite1, &sat, NULL );
    BOOL bPipeOk2 = CreatePipe( &hPipeRead2, &hPipeWrite2, &sat, NULL );
    if( !bPipeOk1 || !bPipeOk2 )
    {
    return;
    }
    STARTUPINFO StartUpInfo = {0};
    PROCESS_INFORMATION ProInfo = {0};
        StartUpInfo.cb = sizeof( StartUpInfo );
        StartUpInfo.lpReserved = NULL;
        StartUpInfo.dwFlags = 0;
        StartUpInfo.cbReserved2 = 0;
        StartUpInfo.lpReserved2 = NULL; 
        StartUpInfo.lpDesktop = NULL;
        StartUpInfo.lpTitle = NULL;
        StartUpInfo.dwX = 0;
        StartUpInfo.dwY = 0;
        StartUpInfo.dwXSize = 0;
        StartUpInfo.dwYSize = 0;
        StartUpInfo.dwXCountChars = 0;
        StartUpInfo.dwYCountChars = 0;
        StartUpInfo.dwFillAttribute = 0;
        StartUpInfo.dwFlags = NULL;
        StartUpInfo.wShowWindow = SW_SHOW;
        StartUpInfo.hStdInput = hPipeRead1;
        StartUpInfo.hStdOutput = hPipeWrite2;//NULL;
        StartUpInfo.hStdError = hPipeWrite2;//NULL;
    BOOL bProOk = CreateProcess( NULL, "cmd",
    NULL, NULL, TRUE, NULL, NULL, NULL,
    &StartUpInfo, &ProInfo );
    if( !bProOk )
    {
    return;
    }
    CloseHandle( hPipeRead1 );
    CloseHandle( hPipeWrite2 );

    char szCmdLine[1024] = "dir\r\n";
    // 写入命令
    ULONG uWrited = 0;
    BOOL bWriteOk = WriteFile( hPipeWrite1, szCmdLine, strlen(szCmdLine), &uWrited, NULL );
    char szWrited[256] = {0};
    sprintf( szWrited, "writed: %d", uWrited );
    MessageBox( szWrited ); // 关闭进程
    CloseHandle( hPipeRead2 );
    CloseHandle( hPipeWrite1 );
    CloseHandle( ProInfo.hProcess); return;
    }
      

  10.   

    http://www.codeguru.com/Cpp/W-D/console/redirection/article.php/c541/
      

  11.   

    我把它改成这样你试一试。
    void CCmdPipeDlg::OnButtonDo() 
    {
    HANDLE hProcess = ::GetCurrentProcess(); // Set up the security attributes struct.
    SECURITY_ATTRIBUTES sa;
    ::ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
    sa.nLength= sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;
    HANDLE m_hStdIn, m_hStdOut, m_hStdErr;
    HANDLE hStdInWriteTmp, hStdOutReadTmp, hStdErrReadTmp;
    HANDLE m_hStdInWrite, m_hStdOutRead, m_hStdErrRead;
    // Create the child stdin pipe.
    VERIFY(::CreatePipe(&m_hStdIn, &hStdInWriteTmp, &sa, 0)); // Create the child stdout pipe.
    VERIFY(::CreatePipe(&hStdOutReadTmp, &m_hStdOut, &sa, 0));

    // Create the child stderr pipe.
    VERIFY(::CreatePipe(&hStdErrReadTmp, &m_hStdErr, &sa, 0)); VERIFY(::DuplicateHandle(hProcess, hStdInWriteTmp,
    hProcess, &m_hStdInWrite, 0, FALSE, DUPLICATE_SAME_ACCESS)); VERIFY(::DuplicateHandle(hProcess, hStdOutReadTmp,
    hProcess, &m_hStdOutRead, 0, FALSE, DUPLICATE_SAME_ACCESS)); VERIFY(::DuplicateHandle(hProcess, hStdErrReadTmp,
    hProcess, &m_hStdErrRead, 0, FALSE, DUPLICATE_SAME_ACCESS)); // Close inheritable copies of the handles you do not want to be
    // inherited. VERIFY(::CloseHandle(hStdInWriteTmp));
    VERIFY(::CloseHandle(hStdOutReadTmp));
    VERIFY(::CloseHandle(hStdErrReadTmp)); STARTUPINFO StartUpInfo = {0};
    PROCESS_INFORMATION ProInfo = {0};
             StartUpInfo.cb = sizeof( StartUpInfo );
             StartUpInfo.wShowWindow = SW_HIDE;  //want see consle set this SW_SHOW
    StartUpInfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
    StartUpInfo.hStdOutput = m_hStdOut;
    StartUpInfo.hStdInput  = m_hStdIn;
    StartUpInfo.hStdError  = m_hStdErr;

    BOOL bProOk = CreateProcess( NULL, "cmd",
    NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL,
    &StartUpInfo, &ProInfo );
    if( !bProOk )
    {
    return;
    }
    // Close any unnecessary handles.
    VERIFY(::CloseHandle(ProInfo.hThread));

    WaitForInputIdle(ProInfo.hProcess,10000);
    char szCmdLine[1024] = "dir\r\n";
    // Write Command
    ULONG uWrited = 0;
    BOOL bWriteOk = WriteFile( m_hStdInWrite, szCmdLine, strlen(szCmdLine), &uWrited, NULL );
    char szWrited[256] = {0};
    sprintf( szWrited, "writed: %d", uWrited );
    MessageBox( szWrited );
             DWORD dwRead = 0; 
             CHAR chBuf[1024] = {0};  // Read output from the child process, and write to parent's STDOUT. 
             if( !ReadFile( m_hStdOutRead, chBuf, 1024, &dwRead, 
             NULL) || dwRead == 0) 
    {
    TRACE("Read File Error!\n");
    }
    MessageBox( chBuf );
    // Close Handle
    VERIFY( CloseHandle( m_hStdOut ) );
    VERIFY( CloseHandle( m_hStdIn ) );
    VERIFY( CloseHandle( m_hStdErr ) );
    VERIFY( CloseHandle( ProInfo.hProcess) );
    VERIFY( CloseHandle( m_hStdInWrite ) );
    VERIFY( CloseHandle( m_hStdOutRead ) );
    VERIFY( CloseHandle( m_hStdErrRead ) );

    return;
    }