C++Builder Logo
Redirecting stdout from a console application to a TMemo Rediriger la sortie stdout d'une console vers un TMemo

First of all, I have to thank Dima Shamroni  who had posted a working example on microsoft.public.vc.mfc and Matt Brunk for his article on www.codeguru.com. This tip is based on their code and simply rewritten for C++ Builder. Je tiens d'abord à remercier Dima Shamroni qui a posté un bout de code sur microsoft.public.vc.mfc et Matt Brunk pour son article sur le site www.codeguru.com. Mon code n'est qu'une adaptation du leur pour C++ Builder.
It may occur that we need to launch a console application and catch its output normally sent to the standard output (STDOUT). This code snippet catch the stdout of the console and send it to a TMemo using anonymous pipe (unnamed pipe). Il peut arriver qu'on doive lancer une application dans une console et connaître ce que le programme a affiché dans la console en utilisant le standard output (STDOUT). Le code ci-dessous détourne le stdout de la console et l'envoie vers un TMemo en utilisant un anonimous pipe (unnamed pipe).

void __fastcall TForm1::Button1Click(TObject *Sender) 

  //create pipe for the console stdout 
  SECURITY_ATTRIBUTES sa; 
  ZeroMemory(&sa,sizeof(SECURITY_ATTRIBUTES)); 
  sa.nLength=sizeof(SECURITY_ATTRIBUTES); 
  sa.bInheritHandle=true
  sa.lpSecurityDescriptor=NULL; 
  HANDLE ReadPipeHandle; 
  HANDLE WritePipeHandle;       // not used here 
  if(!CreatePipe(&ReadPipeHandle,&WritePipeHandle,&sa,0)) 
        RaiseLastWin32Error(); 

  //Create a Console 
  STARTUPINFO si; 
  ZeroMemory(&si,sizeof(STARTUPINFO)); 
  si.cb=sizeof(STARTUPINFO); 
  si.dwFlags=STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES; 
  si.wShowWindow=SW_HIDE; 
  si.hStdOutput=WritePipeHandle; 
  si.hStdError=WritePipeHandle; 

  PROCESS_INFORMATION pi; 
  ZeroMemory(&pi,sizeof(PROCESS_INFORMATION)); 
  if(!CreateProcess("YourProgram.exe",NULL,NULL,NULL,true,0,NULL,NULL,&si,&pi)) 
      RaiseLastWin32Error(); 

  //Read from pipe 
  char Data[1024]; 
  for (;;) 
  { 
    DWORD BytesRead; 
    DWORD TotalBytes; 
    DWORD BytesLeft; 

    //Check for the presence of data in the pipe 
    if(!PeekNamedPipe(ReadPipeHandle,Data,sizeof(Data),&BytesRead, 
        &TotalBytes,&BytesLeft))RaiseLastWin32Error(); 
    //If there is bytes, read them 
    if(BytesRead) 
    { 
      if(!ReadFile(ReadPipeHandle,Data,sizeof(Data)-1,&BytesRead,NULL)) 
          RaiseLastWin32Error(); 
      Data[BytesRead]='\0'; 
      Memo1->Lines->Add(AnsiString(Data)); 

    } 
    else 
    { 
      //Is the console app terminated? 
      if(WaitForSingleObject(pi.hProcess,0)==WAIT_OBJECT_0)break

    } 
  } 
  CloseHandle(pi.hThread); 
  CloseHandle(pi.hProcess); 
  CloseHandle(ReadPipeHandle); 
  CloseHandle(WritePipeHandle); 

//---------------------------------------------------------------------------