Você está offline; aguardando reconexão

Como gerar processos do console com alças redirecionadas padrão

IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine Translation ou MT), não tendo sido portanto traduzido ou revisto por pessoas. A Microsoft possui artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais, com o objetivo de oferecer em português a totalidade dos artigos existentes na base de dados de suporte. No entanto, a tradução automática não é sempre perfeita, podendo conter erros de vocabulário, sintaxe ou gramática. A Microsoft não é responsável por incoerências, erros ou prejuízos ocorridos em decorrência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza atualizações freqüentes ao software de tradução automática (MT). Obrigado.

Clique aqui para ver a versão em Inglês deste artigo: 190351
Sumário
Este artigo descreve como redirecionar a entrada e saída de um processo filho que recebe entrada da alça de entrada padrão ou envia saída para a alça de saída padrão. A API Win32 permite que aplicativos gerar um processo de console filho com alças redirecionadas padrão. Esse recurso permite que um processo pai enviar e receber a entrada e saída do processo filho.

Observação Alguns aplicativos de console com base não usam as alças de padrão para suas operações (es) de entrada/saída. A API do Win32 não dá suporte redirecionamento desses processos.
Mais Informações
A API CreateProcess() através da estrutura STARTUPINFO permite redirecionar as alças de padrão de um processo de console com base filho. Se o membro dwFlags é definido como STARTF_USESTDHANDLES, os seguintes membros STARTUPINFO especificar as alças padrão do processo de console com base em filho:
   HANDLE hStdInput - Standard input handle of the child process.   HANDLE hStdOutput - Standard output handle of the child process.   HANDLE hStdError - Standard error handle of the child process.				
você pode definir essas alças para qualquer uma alça de pipe, identificador de arquivo, ou qualquer alça que pode fazer síncrona lê e grava através da chamada ReadFile() e WriteFile() API. As alças de devem ser herdadas e a API CreateProcess() deve especificar que alças herdáveis devem ser herdado por processo filho especificando verdadeiro no parâmetro bInheritHandles. Se o processo pai apenas quiser redirecionar uma ou duas alças padrão, especificando GetStdHandle() para identificadores específicos fará com que o filho para criar o identificador padrão como faria normalmente sem redirecionamento. Por exemplo, se o processo pai só precisa redirecionar a saída padrão e erro do processo filho, em seguida, o membro hStdInput da estrutura STARTUPINFO é preenchido da seguinte maneira:
   hStdInput = GetStdHandle(STD_INPUT_HANDLE);				
Observação filho processos que usam funções, tempo de execução C como printf() e fprintf() podem se comportar mal quando redirecionados. As funções de tempo de execução C mantém separados buffers de E/S. Quando redirecionados, esses buffers não podem ser liberados imediatamente após chamar cada E/S. Como resultado, a saída para o pipe de redirecionamento de uma chamada printf() ou a entrada de uma chamada getch() não é liberada imediatamente e atrasos, às vezes, infinito atrasos ocorrem. Esse problema é evitado se o processo filho libera os buffers de E/S após cada chamada para uma função de E/S de tempo de execução C. Somente o processo filho pode liberar seus buffers de E/S de tempo de execução C. Um processo pode liberar seus buffers de E/S de tempo de execução C, chamando a função fflush().

Observação O Windows 95 e Windows 98 requerem uma etapa extra quando você redireciona as alças de padrão de determinados processos filho.

O exemplo a seguir redireciona a entrada padrão, saída e erro do processo filho especificado na chamada de CreateProcess. Este exemplo redireciona o processo de console fornecida (Child.c).

Código de exemplo

   /*++      Copyright (c) 1998  Microsoft Corporation      Module Name:         Redirect.c      Description:          This sample illustrates how to spawn a child console based          application with redirected standard handles.          The following import libraries are required:          user32.lib      Dave McPherson (davemm)   11-March-98   --*/    #include<windows.h>   #pragma comment(lib, "User32.lib")   void DisplayError(char *pszAPI);   void ReadAndHandleOutput(HANDLE hPipeRead);   void PrepAndLaunchRedirectedChild(HANDLE hChildStdOut,                                     HANDLE hChildStdIn,                                     HANDLE hChildStdErr);   DWORD WINAPI GetAndSendInputThread(LPVOID lpvThreadParam);   HANDLE hChildProcess = NULL;   HANDLE hStdIn = NULL; // Handle to parents std input.   BOOL bRunThread = TRUE;   void main ()   {      HANDLE hOutputReadTmp,hOutputRead,hOutputWrite;      HANDLE hInputWriteTmp,hInputRead,hInputWrite;      HANDLE hErrorWrite;      HANDLE hThread;      DWORD ThreadId;      SECURITY_ATTRIBUTES sa;      // Set up the security attributes struct.      sa.nLength= sizeof(SECURITY_ATTRIBUTES);      sa.lpSecurityDescriptor = NULL;      sa.bInheritHandle = TRUE;      // Create the child output pipe.      if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0))         DisplayError("CreatePipe");      // Create a duplicate of the output write handle for the std error      // write handle. This is necessary in case the child application      // closes one of its std output handles.      if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite,                           GetCurrentProcess(),&hErrorWrite,0,                           TRUE,DUPLICATE_SAME_ACCESS))         DisplayError("DuplicateHandle");      // Create the child input pipe.      if (!CreatePipe(&hInputRead,&hInputWriteTmp,&sa,0))         DisplayError("CreatePipe");      // Create new output read handle and the input write handles. Set      // the Properties to FALSE. Otherwise, the child inherits the      // properties and, as a result, non-closeable handles to the pipes      // are created.      if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp,                           GetCurrentProcess(),                           &hOutputRead, // Address of new handle.                           0,FALSE, // Make it uninheritable.                           DUPLICATE_SAME_ACCESS))         DisplayError("DupliateHandle");      if (!DuplicateHandle(GetCurrentProcess(),hInputWriteTmp,                           GetCurrentProcess(),                           &hInputWrite, // Address of new handle.                           0,FALSE, // Make it uninheritable.                           DUPLICATE_SAME_ACCESS))      DisplayError("DupliateHandle");      // Close inheritable copies of the handles you do not want to be      // inherited.      if (!CloseHandle(hOutputReadTmp)) DisplayError("CloseHandle");      if (!CloseHandle(hInputWriteTmp)) DisplayError("CloseHandle");      // Get std input handle so you can close it and force the ReadFile to      // fail when you want the input thread to exit.      if ( (hStdIn = GetStdHandle(STD_INPUT_HANDLE)) ==                                                INVALID_HANDLE_VALUE )         DisplayError("GetStdHandle");      PrepAndLaunchRedirectedChild(hOutputWrite,hInputRead,hErrorWrite);      // Close pipe handles (do not continue to modify the parent).      // You need to make sure that no handles to the write end of the      // output pipe are maintained in this process or else the pipe will      // not close when the child process exits and the ReadFile will hang.      if (!CloseHandle(hOutputWrite)) DisplayError("CloseHandle");      if (!CloseHandle(hInputRead )) DisplayError("CloseHandle");      if (!CloseHandle(hErrorWrite)) DisplayError("CloseHandle");      // Launch the thread that gets the input and sends it to the child.      hThread = CreateThread(NULL,0,GetAndSendInputThread,                              (LPVOID)hInputWrite,0,&ThreadId);      if (hThread == NULL) DisplayError("CreateThread");      // Read the child's output.      ReadAndHandleOutput(hOutputRead);      // Redirection is complete      // Force the read on the input to return by closing the stdin handle.      if (!CloseHandle(hStdIn)) DisplayError("CloseHandle");      // Tell the thread to exit and wait for thread to die.      bRunThread = FALSE;      if (WaitForSingleObject(hThread,INFINITE) == WAIT_FAILED)         DisplayError("WaitForSingleObject");      if (!CloseHandle(hOutputRead)) DisplayError("CloseHandle");      if (!CloseHandle(hInputWrite)) DisplayError("CloseHandle");   }   ///////////////////////////////////////////////////////////////////////    // PrepAndLaunchRedirectedChild   // Sets up STARTUPINFO structure, and launches redirected child.   ///////////////////////////////////////////////////////////////////////    void PrepAndLaunchRedirectedChild(HANDLE hChildStdOut,                                     HANDLE hChildStdIn,                                     HANDLE hChildStdErr)   {      PROCESS_INFORMATION pi;      STARTUPINFO si;      // Set up the start up info struct.      ZeroMemory(&si,sizeof(STARTUPINFO));      si.cb = sizeof(STARTUPINFO);      si.dwFlags = STARTF_USESTDHANDLES;      si.hStdOutput = hChildStdOut;      si.hStdInput  = hChildStdIn;      si.hStdError  = hChildStdErr;      // Use this if you want to hide the child:      //     si.wShowWindow = SW_HIDE;      // Note that dwFlags must include STARTF_USESHOWWINDOW if you want to      // use the wShowWindow flags.      // Launch the process that you want to redirect (in this case,      // Child.exe). Make sure Child.exe is in the same directory as      // redirect.c launch redirect from a command line to prevent location      // confusion.      if (!CreateProcess(NULL,"Child.EXE",NULL,NULL,TRUE,                         CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi))         DisplayError("CreateProcess");      // Set global child process handle to cause threads to exit.      hChildProcess = pi.hProcess;      // Close any unnecessary handles.      if (!CloseHandle(pi.hThread)) DisplayError("CloseHandle");   }   ///////////////////////////////////////////////////////////////////////    // ReadAndHandleOutput   // Monitors handle for input. Exits when child exits or pipe breaks.   ///////////////////////////////////////////////////////////////////////    void ReadAndHandleOutput(HANDLE hPipeRead)   {      CHAR lpBuffer[256];      DWORD nBytesRead;      DWORD nCharsWritten;      while(TRUE)      {         if (!ReadFile(hPipeRead,lpBuffer,sizeof(lpBuffer),                                          &nBytesRead,NULL) || !nBytesRead)         {            if (GetLastError() == ERROR_BROKEN_PIPE)               break; // pipe done - normal exit path.            else               DisplayError("ReadFile"); // Something bad happened.         }         // Display the character read on the screen.         if (!WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),lpBuffer,                           nBytesRead,&nCharsWritten,NULL))            DisplayError("WriteConsole");      }   }   ///////////////////////////////////////////////////////////////////////    // GetAndSendInputThread   // Thread procedure that monitors the console for input and sends input   // to the child process through the input pipe.   // This thread ends when the child application exits.   ///////////////////////////////////////////////////////////////////////    DWORD WINAPI GetAndSendInputThread(LPVOID lpvThreadParam)   {      CHAR read_buff[256];      DWORD nBytesRead,nBytesWrote;      HANDLE hPipeWrite = (HANDLE)lpvThreadParam;      // Get input from our console and send it to child through the pipe.      while (bRunThread)      {         if(!ReadConsole(hStdIn,read_buff,1,&nBytesRead,NULL))            DisplayError("ReadConsole");         read_buff[nBytesRead] = '\0'; // Follow input with a NULL.         if (!WriteFile(hPipeWrite,read_buff,nBytesRead,&nBytesWrote,NULL))         {            if (GetLastError() == ERROR_NO_DATA)               break; // Pipe was closed (normal exit path).            else            DisplayError("WriteFile");         }      }      return 1;   }   ///////////////////////////////////////////////////////////////////////    // DisplayError   // Displays the error number and corresponding message.   ///////////////////////////////////////////////////////////////////////    void DisplayError(char *pszAPI)   {       LPVOID lpvMessageBuffer;       CHAR szPrintBuffer[512];       DWORD nCharsWritten;       FormatMessage(                FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,                NULL, GetLastError(),                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),                (LPTSTR)&lpvMessageBuffer, 0, NULL);       wsprintf(szPrintBuffer,         "ERROR: API    = %s.\n   error code = %d.\n   message    = %s.\n",                pszAPI, GetLastError(), (char *)lpvMessageBuffer);       WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),szPrintBuffer,                     lstrlen(szPrintBuffer),&nCharsWritten,NULL);       LocalFree(lpvMessageBuffer);       ExitProcess(GetLastError());   }   //////////////////////////////////////////////////////////////////////    // child.c   // Echoes all input to stdout. This will be redirected by the redirect   // sample. Compile and build child.c as a Win32 Console application and   // put it in the same directory as the redirect sample.   //    #include<windows.h>   #include<stdio.h>   #include<string.h>   void main ()   {      FILE*    fp;      CHAR     szInput[1024];      // Open the console. By doing this, you can send output directly to      // the console that will not be redirected.      fp = fopen("CON", "w");      if (!fp) {         printf("Error opening child console - perhaps there is none.\n");         fflush(NULL);      }      else      {      // Write a message direct to the console (will not be redirected).         fprintf(fp,"This data is being printed directly to the\n");         fprintf(fp,"console and will not be redirected.\n\n");         fprintf(fp,"Since the standard input and output have been\n");         fprintf(fp,"redirected data sent to and from those handles\n");         fprintf(fp,"will be redirected.\n\n");         fprintf(fp,"To send data to the std input of this process.\n");         fprintf(fp,"Click on the console window of the parent process\n");         fprintf(fp,"(redirect), and enter data from it's console\n\n");         fprintf(fp,"To exit this process send the string 'exit' to\n");         fprintf(fp,"it's standard input\n");         fflush(fp);      }      ZeroMemory(szInput,1024);      while (TRUE)      {         gets(szInput);         printf("Child echoing [%s]\n",szInput);         fflush(NULL);  // Must flush output buffers or else redirection                        // will be problematic.         if (!_stricmp(szInput,"Exit") )            break;         ZeroMemory(szInput,strlen(szInput) );      }   }
Referências
Documentação do SDK do MSDN Library: CreateProcess(); STARTUPINFO estrutura

Herdar de exemplo no SDK da plataforma Win32 em:
   \MSSDK\samples\winbase\ipc\inherit				
Herança de redirecionamento redirecionado stdhandles

Aviso: este artigo foi traduzido automaticamente

Propriedades

ID do Artigo: 190351 - Última Revisão: 11/21/2006 15:28:50 - Revisão: 7.1

Interface de Programação de Aplicativos do Microsoft Win32

  • kbmt kbapi kbconsole kbfaq kbhowto kbipc kbkernbase KB190351 KbMtpt
Comentários