Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1683005
  • 博文数量: 584
  • 博客积分: 13857
  • 博客等级: 上将
  • 技术积分: 11883
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-16 09:34

分类: WINDOWS

2011-04-19 14:36:06

CreatePipe创建的是匿名管道,匿名管道数据只能单向流动,所以如果要能对子进程输入数据也能读出执行结果,就是创建两个匿名管道了,一个用来输 入数据到子进程,一个用来从子进程中读出数据。CreatePipe分别有两个HANDLE的读写句柄,把这两个管道的读写句柄分别用在 CreateProcess()的STARTINFO的参数上,然后创建进程就可以了。


  1. HANDLE hSTDINWrite,hSTDINRead,hSTDINWriteup; //用于重定向子进程输入的句柄
  2. HANDLE hSTDOUTWrite,hSTDOUTRead, hSTDOUTReadup; //用于重定向子进程输出的句柄
  3. SECURITY_ATTRIBUTES sa;

  4. sa.bInheritHandle = true;
  5. sa.lpSecurityDescriptor = NULL;
  6. sa.nLength = sizeof(sa);
  7. //创建子进程输出匿名管道
  8. if( !CreatePipe(&hSTDOUTRead, &hSTDOUTWrite, &sa,0) )
  9. {
  10. AfxMessageBox( "Create STDOUT pipe failed ");
  11. return 0;
  12. }

  13. if( !DuplicateHandle( ::GetCurrentProcess(), hSTDOUTRead, ::GetCurrentProcess(), &hSTDOUTReadup, 0, false,DUPLICATE_SAME_ACCESS) )
  14. {
  15. AfxMessageBox( "DuplicateHandle failed ");
  16. return 0;
  17. }
  18. ::CloseHandle( hSTDOUTRead );

  19. //创建子进程输入匿名管道
  20. if( !CreatePipe(&hSTDINRead, &hSTDINWrite, &sa,0) )
  21. {
  22. AfxMessageBox( "Create STDIN pipe failed ");
  23. return 0;
  24. }
  25. if( !DuplicateHandle( ::GetCurrentProcess(), hSTDINWrite, ::GetCurrentProcess(), &hSTDINWriteup, 0, false,DUPLICATE_SAME_ACCESS) )
  26. {
  27. AfxMessageBox( "DuplicateHandle failed ");
  28. return 0;
  29. }
  30. ::CloseHandle( hSTDINWrite );


  31. CTestpipeDlg *pDlg = (CTestpipeDlg *)lpData;
  32. PROCESS_INFORMATION pi;
  33. STARTUPINFO si;
  34. ZeroMemory( &si, sizeof(si));


  35. si.cb = sizeof(STARTUPINFO);
  36. si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
  37. si.wShowWindow = SW_HIDE;
  38. si.hStdInput = hSTDINRead; //重定向子进程输入
  39. si.hStdOutput = hSTDOUTWrite; //重定向子进程输入
  40. si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
  41. if( !::CreateProcess(NULL, (char *)(LPCSTR)pDlg-> m_strCmd, NULL, NULL, true, 0,NULL,NULL,&si,&pi) )
  42. {
  43. AfxMessageBox( "create process failed ");
  44. return 0;
  45. }

  46. char strData[1024];
  47. const char *strIn = "2 3\n2 4\n4 67\n0 0\n ";
  48. pDlg-> m_strOut = " ";
  49. ::SendMessage(pDlg-> m_hWnd, WM_UPDATE_MYDATA,0,0);
  50. DWORD dwBytes = 0;

  51. ::CloseHandle( hSTDINRead );
  52.                   //将数据写入子进程,我在子进程中进行的是对strIn的每两个数进行相加操作
  53. ::WriteFile( hSTDINWriteup, strIn, strlen(strIn), &dwBytes, NULL);

  54. //在调用ReadFile前必须关闭该句柄,否则由于父进程的管道写入端有未关闭的Write句柄,ReadFile最后无法返回0
  55. ::CloseHandle( hSTDOUTWrite );

  56. //从子进程中读出执行结果
  57. while( ::ReadFile( hSTDOUTReadup, strData, sizeof(strData), &dwBytes, NULL) )
  58. {
  59. strData[dwBytes] = '\0 ';
  60. pDlg-> m_strOut += strData;
  61. ::SendMessage(pDlg-> m_hWnd, WM_UPDATE_MYDATA,0,0);
  62. }


  63. ::WaitForSingleObject( pi.hProcess, INFINITE);
  64. ::CloseHandle( hSTDOUTReadup );
  65. ::CloseHandle( hSTDINWriteup );
  66. ::CloseHandle(pi.hProcess);
  67. ::CloseHandle(pi.hThread);


  1. //网上抄来的,供参考
  2. /*++

  3.             Copyright (c) 1998 Microsoft Corporation

  4.             Module Name:

  5.                   Redirect.c

  6.             Description:
  7.                     This sample illustrates how to spawn a child console based
  8.                     application with redirected standard handles.

  9.                     The following import libraries are required:
  10.                     user32.lib

  11.             Dave McPherson (davemm) 11-March-98

  12.       --*/

  13.       #include <windows.h>

  14.       void DisplayError(char *pszAPI);
  15.       void ReadAndHandleOutput(HANDLE hPipeRead);
  16.       void PrepAndLaunchRedirectedChild(HANDLE hChildStdOut,
  17.                                                                           HANDLE hChildStdIn,
  18.                                                                           HANDLE hChildStdErr);
  19.       DWORD WINAPI GetAndSendInputThread(LPVOID lpvThreadParam);

  20.       HANDLE hChildProcess = NULL;
  21.       HANDLE hStdIn = NULL; // Handle to parents std input.
  22.       BOOL bRunThread = TRUE;


  23.       void main ()
  24.       {
  25.             HANDLE hOutputReadTmp,hOutputRead,hOutputWrite;
  26.             HANDLE hInputWriteTmp,hInputRead,hInputWrite;
  27.             HANDLE hErrorWrite;
  28.             HANDLE hThread;
  29.             DWORD ThreadId;
  30.             SECURITY_ATTRIBUTES sa;


  31.             // Set up the security attributes struct.
  32.             sa.nLength= sizeof(SECURITY_ATTRIBUTES);
  33.             sa.lpSecurityDescriptor = NULL;
  34.             sa.bInheritHandle = TRUE;


  35.             // Create the child output pipe.
  36.             if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0))
  37.                   DisplayError( "CreatePipe ");


  38.             // Create a duplicate of the output write handle for the std error
  39.             // write handle. This is necessary in case the child application
  40.             // closes one of its std output handles.
  41.             if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite,
  42.                                                       GetCurrentProcess(),&hErrorWrite,0,
  43.                                                       TRUE,DUPLICATE_SAME_ACCESS))
  44.                   DisplayError( "DuplicateHandle ");


  45.             // Create the child input pipe.
  46.             if (!CreatePipe(&hInputRead,&hInputWriteTmp,&sa,0))
  47.                   DisplayError( "CreatePipe ");


  48.             // Create new output read handle and the input write handles. Set
  49.             // the Properties to FALSE. Otherwise, the child inherits the
  50.             // properties and, as a result, non-closeable handles to the pipes
  51.             // are created.
  52.             if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp,
  53.                                                       GetCurrentProcess(),
  54.                                                       &hOutputRead, // Address of new handle.
  55.                                                       0,FALSE, // Make it uninheritable.
  56.                                                       DUPLICATE_SAME_ACCESS))
  57.                   DisplayError( "DupliateHandle ");

  58.             if (!DuplicateHandle(GetCurrentProcess(),hInputWriteTmp,
  59.                                                       GetCurrentProcess(),
  60.                                                       &hInputWrite, // Address of new handle.
  61.                                                       0,FALSE, // Make it uninheritable.
  62.                                                       DUPLICATE_SAME_ACCESS))
  63.             DisplayError( "DupliateHandle ");


  64.             // Close inheritable copies of the handles you do not want to be
  65.             // inherited.
  66.             if (!CloseHandle(hOutputReadTmp)) DisplayError( "CloseHandle ");
  67.             if (!CloseHandle(hInputWriteTmp)) DisplayError( "CloseHandle ");


  68.             // Get std input handle so you can close it and force the ReadFile to
  69.             // fail when you want the input thread to exit.
  70.             if ( (hStdIn = GetStdHandle(STD_INPUT_HANDLE)) ==
  71.                                                                                                 INVALID_HANDLE_VALUE )
  72.                   DisplayError( "GetStdHandle ");

  73.             PrepAndLaunchRedirectedChild(hOutputWrite,hInputRead,hErrorWrite);


  74.             // Close pipe handles (do not continue to modify the parent).
  75.             // You need to make sure that no handles to the write end of the
  76.             // output pipe are maintained in this process or else the pipe will
  77.             // not close when the child process exits and the ReadFile will hang.
  78.             if (!CloseHandle(hOutputWrite)) DisplayError( "CloseHandle ");
  79.             if (!CloseHandle(hInputRead )) DisplayError( "CloseHandle ");
  80.             if (!CloseHandle(hErrorWrite)) DisplayError( "CloseHandle ");


  81.             // Launch the thread that gets the input and sends it to the child.
  82.             hThread = CreateThread(NULL,0,GetAndSendInputThread,
  83.                                                             (LPVOID)hInputWrite,0,&ThreadId);
  84.             if (hThread == NULL) DisplayError( "CreateThread ");


  85.             // Read the child 's output.
  86.             ReadAndHandleOutput(hOutputRead);
  87.             // Redirection is complete


  88.             // Force the read on the input to return by closing the stdin handle.
  89.             if (!CloseHandle(hStdIn)) DisplayError( "CloseHandle ");


  90.             // Tell the thread to exit and wait for thread to die.
  91.             bRunThread = FALSE;

  92.             if (WaitForSingleObject(hThread,INFINITE) == WAIT_FAILED)
  93.                   DisplayError( "WaitForSingleObject ");

  94.             if (!CloseHandle(hOutputRead)) DisplayError( "CloseHandle ");
  95.             if (!CloseHandle(hInputWrite)) DisplayError( "CloseHandle ");
  96.       }


  97.       ///////////////////////////////////////////////////////////////////////
  98.       // PrepAndLaunchRedirectedChild
  99.       // Sets up STARTUPINFO structure, and launches redirected child.
  100.       ///////////////////////////////////////////////////////////////////////
  101.       void PrepAndLaunchRedirectedChild(HANDLE hChildStdOut,
  102.                                                                           HANDLE hChildStdIn,
  103.                                                                           HANDLE hChildStdErr)
  104.       {
  105.             PROCESS_INFORMATION pi;
  106.             STARTUPINFO si;

  107.             // Set up the start up info struct.
  108.             ZeroMemory(&si,sizeof(STARTUPINFO));
  109.             si.cb = sizeof(STARTUPINFO);
  110.             si.dwFlags = STARTF_USESTDHANDLES;
  111.             si.hStdOutput = hChildStdOut;
  112.             si.hStdInput = hChildStdIn;
  113.             si.hStdError = hChildStdErr;
  114.             // Use this if you want to hide the child:
  115.             // si.wShowWindow = SW_HIDE;
  116.             // Note that dwFlags must include STARTF_USESHOWWINDOW if you want to
  117.             // use the wShowWindow flags.


  118.             // Launch the process that you want to redirect (in this case,
  119.             // Child.exe). Make sure Child.exe is in the same directory as
  120.             // redirect.c launch redirect from a command line to prevent location
  121.             // confusion.
  122.             if (!CreateProcess(NULL, "d:\\winnt\\system32\\cmd.exe ",NULL,NULL,TRUE,
  123.                                                   CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi))
  124.                   DisplayError( "CreateProcess ");


  125.             // Set global child process handle to cause threads to exit.
  126.             hChildProcess = pi.hProcess;


  127.             // Close any unnecessary handles.
  128.             if (!CloseHandle(pi.hThread)) DisplayError( "CloseHandle ");
  129.       }


  130.       ///////////////////////////////////////////////////////////////////////
  131.       // ReadAndHandleOutput
  132.       // Monitors handle for input. Exits when child exits or pipe breaks.
  133.       ///////////////////////////////////////////////////////////////////////
  134.       void ReadAndHandleOutput(HANDLE hPipeRead)
  135.       {
  136.             CHAR lpBuffer[256];
  137.             DWORD nBytesRead;
  138.             DWORD nCharsWritten;

  139.             while(TRUE)
  140.             {
  141.                   if (!ReadFile(hPipeRead,lpBuffer,sizeof(lpBuffer),
  142.                                                                                     &nBytesRead,NULL) || !nBytesRead)
  143.                   {
  144.                         if (GetLastError() == ERROR_BROKEN_PIPE)
  145.                               break; // pipe done - normal exit path.
  146.                         else
  147.                               DisplayError( "ReadFile "); // Something bad happened.
  148.                   }

  149.                   // Display the character read on the screen.
  150.                   if (!WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),lpBuffer,
  151.                                                       nBytesRead,&nCharsWritten,NULL))
  152.                         DisplayError( "WriteConsole ");
  153.             }
  154.       }



  1. ///////////////////////////////////////////////////////////////////////
  2.       // GetAndSendInputThread
  3.       // Thread procedure that monitors the console for input and sends input
  4.       // to the child process through the input pipe.
  5.       // This thread ends when the child application exits.
  6.       ///////////////////////////////////////////////////////////////////////
  7.       DWORD WINAPI GetAndSendInputThread(LPVOID lpvThreadParam)
  8.       {
  9.             CHAR read_buff[256];
  10.             DWORD nBytesRead,nBytesWrote;
  11.             HANDLE hPipeWrite = (HANDLE)lpvThreadParam;

  12.             // Get input from our console and send it to child through the pipe.
  13.             while (bRunThread)
  14.             {
  15.                   if(!ReadConsole(hStdIn,read_buff,1,&nBytesRead,NULL))
  16.                         DisplayError( "ReadConsole ");

  17.                   read_buff[nBytesRead] = '\0 '; // Follow input with a NULL.

  18.                   if (!WriteFile(hPipeWrite,read_buff,nBytesRead,&nBytesWrote,NULL))
  19.                   {
  20.                         if (GetLastError() == ERROR_NO_DATA)
  21.                               break; // Pipe was closed (normal exit path).
  22.                         else
  23.                         DisplayError( "WriteFile ");
  24.                   }
  25.             }

  26.             return 1;
  27.       }


  28.       ///////////////////////////////////////////////////////////////////////
  29.       // DisplayError
  30.       // Displays the error number and corresponding message.
  31.       ///////////////////////////////////////////////////////////////////////
  32.       void DisplayError(char *pszAPI)
  33.       {
  34.               LPVOID lpvMessageBuffer;
  35.               CHAR szPrintBuffer[512];
  36.               DWORD nCharsWritten;

  37.               FormatMessage(
  38.                                 FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
  39.                                 NULL, GetLastError(),
  40.                                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  41.                                 (LPTSTR)&lpvMessageBuffer, 0, NULL);

  42.               wsprintf(szPrintBuffer,
  43.                   "ERROR: API = %s.\n error code = %d.\n message = %s.\n ",
  44.                                 pszAPI, GetLastError(), (char *)lpvMessageBuffer);

  45.               WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),szPrintBuffer,
  46.                                           lstrlen(szPrintBuffer),&nCharsWritten,NULL);

  47.               LocalFree(lpvMessageBuffer);
  48.               ExitProcess(GetLastError());
  49.       }

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

  2. 这个是可以输入的(我没有用过输入部分)

  3. 对于 DOS 程序的输出,我认为这个程序是我见过的最好的了,希望对你有用 :)

  4. 文件只需要
  5.         Redirect.cpp
  6.         Redirect.h
  7. 可以派生,用着很好用。








阅读(2622) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~