2010-06-29 56 views
0

寫我創建了兩個管道在 http://msdn.microsoft.com/en-us/library/ms682499%28VS.85%29.aspx未能就管Windows可視化CPP

給出的子進程是一個EXE文件子進程stdin和stdout重定向到父進程。 當使用控制檯執行時,它首先在STDOUT上返回警告,然後詢問STDIN的是/否輸入。 當我從我的cpp程序運行子進程時,讀取管道成功讀取了子進程STDOUT中的警告行,但是當嘗試使用寫入管道向子進程的STDIN發送「是」或「否」時,子程序以某種方式無法接收它。但是當我在父母的STDIN上鍵入時,子進程接收到「是」和「否」。

任何想法爲什麼會發生這種情況?

回答

0

您是否有孩子程序的來源?檢查它如何讀取其輸入(或在此處發佈源代碼)。

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

如果不是,那麼程序可能會使用低級console functions來執行其輸入(可能間接地,例如通過_getch())。在這種情況下,您可能需要使用WriteConsoleInput來模擬輸入。

或者,您的重定向代碼可能存在錯誤。張貼在這裏。

EDIT使用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獲得控制檯輸入句柄。當父母是一個控制檯應用程序時,子控制檯應用程序將與父母共享控制檯。如果父級是GUI應用程序,因此沒有控制檯,請在調用GetStdHandle之前使用AttachConsole函數附加到子進程控制檯,然後在完成調用時調用FreeConsole

+0

它不適用於echo yes | 。我也嘗試過。 – 2010-06-29 11:05:19

+0

@gunjit mishra - 然後,應用程序使用控制檯I/O函數或將其STDIO重新分配給控制檯輸入流。在這兩種情況下,'WriteConsoleInput'都應該有所幫助。 – atzz 2010-06-29 15:07:31

+0

當我在管道句柄上使用writeconsoleinput時,它給出錯誤「非法訪問代碼」。我如何創建一個具有通用讀寫權限的管道。 – 2010-06-30 07:30:43

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(); 



        } 
+0

抱歉前兩行代碼的一部分 – 2010-06-29 12:23:01