无法在管道上编写Windows visual c ++

时间:2010-06-29 08:39:26

标签: c++ windows pipe

我创建了两个管道来将子进程stdin和stdout重定向到父进程,如下所示 http://msdn.microsoft.com/en-us/library/ms682499%28VS.85%29.aspx

子进程是一个exe文件。 当使用控制台执行时,它首先在STDOUT上返回一个警告,然后从STDIN请求是/否输入。 当我从我的cpp程序运行子进程时,读取管道成功地从子进程STDOUT读取警告线但是当尝试使用写入管道向子进程发送“是”或“否”时,子程序以某种方式不接收它。但是当我在父级的STDIN上键入它时,子进程收到yes和no。

知道为什么会这样吗?

2 个答案:

答案 0 :(得分:0)

您是否有儿童计划的来源?检查它是如何读取输入的(或在此处发布源代码)。

您的子程序是否可以使用cmd输入重定向,例如如果你做echo yes | childprogram.exe

如果没有,则程序可能会使用低级别console functions来进行输入(可能是间接的,例如通过_getch())。在这种情况下,您可能必须使用WriteConsoleInput来模拟输入。

或者,您的重定向代码可能存在错误。发布在这里。

编辑使用WriteConsoleInput:

的示例
#include <windows.h>
#include <process.h>
#include <stdlib.h>
#include <stdio.h>

static const INPUT_RECORD SimulatedInput [] =
{
    {KEY_EVENT, {TRUE, 1, 0, 0, {L'e'}, 0}},
    {KEY_EVENT, {TRUE, 1, 0, 0, {L'c'}, 0}},
    {KEY_EVENT, {TRUE, 1, 0, 0, {L'h'}, 0}},
    {KEY_EVENT, {TRUE, 1, 0, 0, {L'o'}, 0}},
    {KEY_EVENT, {TRUE, 1, 0, 0, {L' '}, 0}},
    {KEY_EVENT, {TRUE, 1, 0, 0, {L'T'}, 0}},
    {KEY_EVENT, {TRUE, 1, 0, 0, {L'E'}, 0}},
    {KEY_EVENT, {TRUE, 1, 0, 0, {L'S'}, 0}},
    {KEY_EVENT, {TRUE, 1, 0, 0, {L'T'}, 0}},
    {KEY_EVENT, {TRUE, 1, VK_RETURN, 0, {L'\r'}, 0}},
};

int main( int, char*[] )
{
    printf("\n(type 'exit' to exit the subshell)\n");

    // start a command interpreter asynchronously
    intptr_t process_handle = _spawnlp(_P_NOWAIT, "cmd", "/k", "prompt", "SUBSHELL: ", NULL);

    // get own console handle
    HANDLE con_input_handle = GetStdHandle(STD_INPUT_HANDLE);

    // send input to the console
    DWORD n_written;
    WriteConsoleInputW(con_input_handle, SimulatedInput, _countof(SimulatedInput), &n_written);

    // wait for child process to exit
    _cwait(NULL, process_handle, 0);

    return 0;
}

上面的示例必须编译为控制台程序,因为它使用GetStdHandle来获取控制台输入句柄。当父级是控制台应用程序时,子控制台应用程序将与父级共享控制台。如果parent是一个GUI应用程序,因此没有控制台,请在调用GetStdHandle之前使用AttachConsole函数附加到子进程控制台,然后在完成后调用FreeConsole

答案 1 :(得分:0)

VOID WriteToPipe(VOID) 
{ 
 DWORD  dwWritten; 
  CHAR chBuf[3];
   sprintf(chBuf,"y\r\n");  
  if(logLevel==1) 
log("trying to write y to child\n",1);
 // Read from a file and write its contents to a pipe. 


    if (! WriteFile(hChildStdinWr, chBuf, 3, 
      &dwWritten, NULL)) 
   if(logLevel ==1)
   log("cannot write to child in write\n",1);

 // Close the pipe handle so the child process stops reading. 
 /*
  if (! CloseHandle(hChildStdinWr)) {
   if(logLevel==1)     
     log("Close pipe failed in write \n");
   ExitProcess(0); 
   }
   */
 } 



 void ReadFromPipe(VOID) 
 { 
   DWORD dwRead, dwWritten; 
  CHAR chBuf[MAX]; 

  // Close the write end of the pipe before reading from the 
  // read end of the pipe. 
  log("reading data from child process \n",1 );
  /*if (!CloseHandle(hChildStdoutWr)) {
      cerr<<"Closing handle failed\n";
  ExitProcess(0); 
      }*/

     // Read output from the child process, and write to parent's STDOUT. 

    for(;;)
     { 
      if( !ReadFile( hChildStdoutRd, chBuf, MAX, &dwRead, 
        NULL) || dwRead == 0) break; 
        if (! WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL)) 
         break; 

        if(logLevel ==1) {
        log(chBuf,1);
          log("\n");
         }
        memset(chBuf,NULL,MAX);
       }
        log("finished reading \n",1);
         } 



       BOOL CreateChildProcess() 
        { 
          TCHAR szCmdline[1024] ;
          if(pool && !submit) {
          sprintf(szCmdline,"program.exe");
         }
         else {    
             sprintf(szCmdline,"command.exe  argument");
             }

             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, 
             szCmdline,     // 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)  {
            ExitProcess(0); 
           }


              return bFuncRetn;
               }



        void execute() {

       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)) {
            ExitProcess(1);
            }
         // Ensure that the read handle to the child process's 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)) {

           ExitProcess(1);
                 }
        // Ensure that the write handle to the child process's pipe for STDIN is not 
                nherited. 
                 SetHandleInformation( hChildStdinWr, HANDLE_FLAG_INHERIT, 0);
             // Now create the child process. 
           fSuccess = CreateChildProcess(host,password,action,username);
          if (! fSuccess) {
        cerr<<"Create process failed";
               ExitProcess(0); 
               }
           CloseHandle(hChildStdinRd);
           CloseHandle(hChildStdoutWr);



              WriteToPipe();
                ReadFromPipe();



                  }