Newsgroup: it.comp.programmare.win32
Titolo: (DISPERATO!) Redirezione StdIn e StdOutput

Premetto che ho letto molto di quello che c'era da leggere....
Copio/incollo la parte del codice che interessa piu' in giu'....
Premetto anche che :
Uso Borland C++Builder 5
Creo un Processo con la CreateProcess. Si tratta di una istanza del
Sicstus Prolog.
Posso eseguirne DUE versioni, una Gui (detta spwin.exe), alla quale i
vari reindirizzamenti non sembrano fare ALCUN effetto, ed una
console-based (o come diavolo si dice), che invece accetta la
redirezione dell'output, piu' o meno(chiamata sicstus.exe)  :)
Non ho problemi ad eseguire una o l'altra basta che funzioni....
Ho una semplice necessita' di reindirizzare tutto l'output ad un file,
( creato magario con la CreateFile, che mi ritorna l'handle che
assegno con si.hStdInput). Non c'e' nel codice, ma se lo faccio sembra
funzionare, sotto certe condizioni, e cioe' usando sicstus.exe
Il mio problema e' inviare comandi a questa finestra che creo con la
CreateProcess. Comandi che invece che essere inseriti da tastiera
devono essere inviati da me....(e ovviamente catturo l'output sul
solito file)
La WriteFile, non sembra fungere, o perlomeno non sembr accettare il
carattere "return" (o "invio", che dovrebbe essere "\n"), visto che
prolog non mi fornisce alcun risultato, segno che NON ha accettato il
comando "invio".
Qualcuno ha idee, suggerimenti ???
La KB di Microsoft non mi aiuta a riguardo, e ho trovato un documento
ufficiale Borland dal quale ho tratto il codice seguente. Ma
ovviamente non funziona come dovrebbe....
Ci sto sbattendo la testa da una settimana, QUALSIASI tipo di aiuto in
e-mail, icq, piccione viaggiatore anche sarebbe MOLTO apprezzato.
Grazie in anticipo
(segue codice)
--- INIZIO ---
void __fastcall TForm1::Button3Click(TObject *Sender)
{
memset (&pi, 0, sizeof(pi));
memset (&si, 0, sizeof(si));
si.cb = sizeof(si);
// *total = *param1+*param2+*param3+*param4;
AnsiString tot= msg1+" "+msg2+" "+msg3+" "+msg4;
char * tot2 = new char [tot.Length()+1];
strcpy (tot2,tot.c_str());
void *pip;
long  *bitvar32 ;
 char buf[1024];           //i/o buffer
 SECURITY_DESCRIPTOR sd;      //security information for pipes
 HANDLE newstdin,newstdout,read_stdout,write_stdin;  //pipe handles
 sa.lpSecurityDescriptor = NULL;
 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
 sa.bInheritHandle = true;         //allow inheritable handles
 if (!CreatePipe(&newstdin,&write_stdin,&sa,0))   //create stdin pipe
  {
    ShowMessage("CreatePipe");
    //getch();
    return;
  }
 if (!CreatePipe(&read_stdout,&newstdout,&sa,0))  //create stdout pipe
  {
    ShowMessage("CreatePipe");
    //getch();
    CloseHandle(newstdin);
    CloseHandle(write_stdin);
    return;
  }
  GetStartupInfo(&si);      //set startupinfo for the spawned process
  /*
  The dwFlags member tells CreateProcess how to make the process.
  STARTF_USESTDHANDLES validates the hStd* members.
STARTF_USESHOWWINDOW
  validates the wShowWindow member.
  */
    si.dwFlags = STARTF_USESTDHANDLES;
 si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
 si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
 si.hStdInput = newstdin;
 char app_spawn[] = "sicstus.exe";
  if (!CreateProcess(NULL,app_spawn,NULL,NULL,TRUE,CREATE_NEW_CONSOLE,
                     NULL,NULL,&si,&pi))
  {
    ShowMessage("CreateProcess");
    //getch();
    CloseHandle(newstdin);
    CloseHandle(newstdout);
    CloseHandle(read_stdout);
    CloseHandle(write_stdin);
    return;
  }
  unsigned long exit=0;  //process exit code
  unsigned long bread;   //bytes read
  unsigned long avail;   //bytes available
  bzero(buf);
*msg='BOH, COMANDO QUALSIASI';  
 WriteFile(write_stdin,msg,5,&bread,NULL); //send it to stdin
*msg='\r';
 WriteFile(write_stdin,msg,5,&bread,NULL); //send it to stdin
 //fflush(stream);
  ShowMessage("ora chiudo tutto");
  TerminateThread(pi.hThread,NULL);
  TerminateProcess(pi.hProcess,NULL);
  CloseHandle(pi.hThread);
  CloseHandle(pi.hProcess);
  CloseHandle(newstdin);            //clean stuff up
  CloseHandle(newstdout);
  CloseHandle(read_stdout);
  CloseHandle(write_stdin);
}  
--- FINE ---
P.S.
Chiedo perdono, ma data la disperazione, ho postato questo msg su piu'
di un NG....:(

Ciao,
io ho ESATTAMENTE il tuo stesso problema!!!
vorrei realizzare in VC++ un editor di script perl,
ma a parte questi 2 dettagli il problema di fondo è sempre quello:
LA REDIREZIONE DI STDIN E STDOUT!
Adesso sono in ufficio e ho zero tempo, se vuoi contattami in email
a lostmind_(et)_
libero.it
 che ci scambiamo un po' di idee... ed insucessi
:)
ciao a presto
Leo

 leggere....
Ma non tutto. Se avessi cercato con Google Groups in questo stesso
newsgroup, avresti trovato due o tre copie dello stesso messaggio (e con
questa fanno tre o quattro) in cui postavo il codice che vedi in fondo.
Sostanzialmente e` necessario appendere "\032\r\n" in fondo alla stringa
che spedisci (in pratica simuli cio` che faresti nella realta`, CTRL-Z +
invio).
BOOL CWndDummy::Filtro_EseguiEsterno( CString& str, CString& prg)
{
 CString dopo;
 STARTUPINFO si;
 PROCESS_INFORMATION pi;
 // Crea una pipe per stdin e una per stdout
 SECURITY_ATTRIBUTES sa;
 HANDLE in[2], out[2];
 ::FillMemory( &sa, sizeof(sa), 0);
 sa.nLength = sizeof(sa);
 sa.bInheritHandle = TRUE;
 if( !::CreatePipe( &out[0], &out[1], &sa, 0))
  return FALSE;
 if( !::CreatePipe( &in[0], &in[1], &sa, 0))
 {
  ::CloseHandle( out[0]);
  ::CloseHandle( out[1]);
  return FALSE;
 }
 // Lancia il filtro esterno, con gli handles modificati  FillMemory(
&si, sizeof(si), 0);
 si.cb = sizeof(si);
 si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
 si.wShowWindow = SW_HIDE;
 si.hStdOutput = si.hStdError = out[1];
 si.hStdInput = in[0];
 if( !::CreateProcess( NULL, (char *)LPCTSTR(prg), NULL, NULL,   TRUE,
0, NULL, NULL, &si, &pi))
 {
  ::CloseHandle( out[0]);
  ::CloseHandle( out[1]);
  ::CloseHandle( in[0]);
  ::CloseHandle( in[1]);
  return FALSE;
 }
 // Chiude i lati che non servono piu`
 ::CloseHandle( out[1]);
 ::CloseHandle( in[0]);
 // Spedisce nell'stdin dell'altro processo il messaggio (con  // EOF
alla fine)...
 str += "\032\r\n";
 int a=0, n=str.GetLength();
 DWORD nIO;
 while( a<n)
 {
  if( !::WriteFile( in[1], LPCTSTR(str.Mid(a)), n-a, &nIO, NULL) ||
    nIO == 0)
   break;
  a += nIO;
 }
 ::CloseHandle( in[1]);
 // ...e legge il risultato dal suo stdout
 char buf[64];
 while( ::ReadFile( out[0], buf, 64, &nIO, NULL) && nIO>0)   dopo +=
CString( buf, nIO);
 ::CloseHandle( out[0]);
 str = dopo;
 return TRUE;
}
--
Lorenzo