Autor Beitrag
.Chef
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1112



BeitragVerfasst: Mo 15.11.04 22:55 
Hallo,

bei der Verwendung einer Pipe bin ich auf ein merkwürdiges Problem gestoßen. Ich fange die Ausgaben einer x-beliebigen Konsolenanwendung ab, um sie in meinem Programm darzustellen. Funktioniert soweit wunderbar.

Erwartet die Anwendung jedoch eine Eingabe, wird nichts zurückgeliefert. Auch nicht bis zu der Stelle, an der die Eingabe verlangt wird. Erst nach Senden der Eingabewerte durch die Pipe wird die komplette(!) Ausgabe der Anwendung zurückgeliefert.

Zwei Fragen dazu: Warum ist das so? Wie kann ich die Ausgabe bis zur Eingabestelle auch vor der Eingabe empfangen?

Gruß,
Jörg

_________________
Die Antworten auf die 5 häufigsten Fragen:
1. Copy(), Pos(), Length() --- 2. DoubleBuffered:=True; --- 3. Application.ProcessMessages bzw. TThread --- 4. ShellExecute() --- 5. Keine Vergleiche von Real-Typen mit "="!
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Mo 15.11.04 23:06 
Das Phänomän ist mir noch nicht aufgefallen, aber vielleicht liegt es daran, dass Windows erst dann die Ausgaben in die Pipe schreibt, wenn der Prozess beendet wird.

Weiterhin wäre evtl. interessant, wie du die Pipe ausliest, d.h. ob Zeichenweise oder gepuffert. Wenn Zeichenweise, dann wundert mich das ein wenig.

Aber bis jetzt hab ich auch Pipes für solche Sachen stets vermieden. Ich nutz für solche Dinge meist Temp-Files, was zwar etwas langsaer ist, aber recht gut zu funktionieren scheint (hab aber noch nicht mit Eingaben an andere Programme gearbeitet).

Evtl. hast du etwas SRC zum Testen des Phänomäns???

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
.Chef Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1112



BeitragVerfasst: Mo 15.11.04 23:26 
BenBE hat folgendes geschrieben:
Das Phänomän ist mir noch nicht aufgefallen, aber vielleicht liegt es daran, dass Windows erst dann die Ausgaben in die Pipe schreibt, wenn der Prozess beendet wird.

Das wäre eine Erklärung. Würde mich allerdings vor große Probleme stellen.

BenBE hat folgendes geschrieben:
Weiterhin wäre evtl. interessant, wie du die Pipe ausliest, d.h. ob Zeichenweise oder gepuffert. Wenn Zeichenweise, dann wundert mich das ein wenig.

Gepuffert. Wie soll das anders gehen?

BenBE hat folgendes geschrieben:
Evtl. hast du etwas SRC zum Testen des Phänomäns???

Der Kern der Sache sieht so aus:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
      ProgRunning:=True;
      repeat
        AtWork:=WaitForSingleObject(ProcInfo.hProcess,100);
        Application.ProcessMessages;
        PeekNamedPipe(StdOutRead,nil,0,nil,@WaitSize,nil);
        if WaitSize > 0 then
        begin
          repeat
            BytesRead:=0;
            ReadFile(StdOutRead,Buffer[0],BufferSize,BytesRead,nil);
            Buffer[BytesRead]:=#0;
            OemToAnsi(Buffer,Buffer);
            Text:=Text+StrPas(Buffer);
          until BytesRead < BufferSize;
        end;
      until AtWork = 0;
      ProgRunning:=False;

Geschrieben wird in einer anderen Prozedur:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
var
  wr, sz: DWORD;
  pc: PChar;
begin
  if ProgRunning then
  begin
    if Key = chr(13then
    begin
      pc:=PChar(Tasten+#13#10);
      sz:=Length(pc);
      WriteFile(StdInWrite,pc[0],sz,wr,nil);

_________________
Die Antworten auf die 5 häufigsten Fragen:
1. Copy(), Pos(), Length() --- 2. DoubleBuffered:=True; --- 3. Application.ProcessMessages bzw. TThread --- 4. ShellExecute() --- 5. Keine Vergleiche von Real-Typen mit "="!
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Mo 15.11.04 23:29 
Das ist "normal".. schau dir einfach mal die Doku zu Suche im MSDN FLUSHFILEBUFFERS an...

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
.Chef Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1112



BeitragVerfasst: Mo 15.11.04 23:50 
Motzi hat folgendes geschrieben:
Das ist "normal".. schau dir einfach mal die Doku zu Suche im MSDN FLUSHFILEBUFFERS an...

Seh ich das richtig, dass ich da 'ne Named Pipe brauche? Hab ich bis jetzt nämlich nicht, das PeekNamedPipe täuscht. ;-)

_________________
Die Antworten auf die 5 häufigsten Fragen:
1. Copy(), Pos(), Length() --- 2. DoubleBuffered:=True; --- 3. Application.ProcessMessages bzw. TThread --- 4. ShellExecute() --- 5. Keine Vergleiche von Real-Typen mit "="!
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Di 16.11.04 00:25 
Nein, nur weil im in dem Beispiel-Code eine Named Pipe verwendet wird heißt das nicht, dass du auch eine Named Pipe brauchst.. IMHO ist es egal um was für ein Objekt es sich handelt, du brauchst eh nur das Handle übergeben..!

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
.Chef Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1112



BeitragVerfasst: Di 16.11.04 11:29 
Motzi hat folgendes geschrieben:
IMHO ist es egal um was für ein Objekt es sich handelt, du brauchst eh nur das Handle übergeben..!

Das Problem ist, dass die anonyme Pipe kein Handle hat, das ich übergeben könnte. Und wenn ich StdOutRead übergebe, passiert nichts.

Etwas ist mir noch aufgefallen, was die ganze Sache noch seltsamer macht: Führe ich z.B. Ping durch die Pipe aus, erscheint die Ausgabe auch häppchenweise, also wie normal. Also die Theorie mit dem "erst nach Programmende" ist damit widerlegt.

_________________
Die Antworten auf die 5 häufigsten Fragen:
1. Copy(), Pos(), Length() --- 2. DoubleBuffered:=True; --- 3. Application.ProcessMessages bzw. TThread --- 4. ShellExecute() --- 5. Keine Vergleiche von Real-Typen mit "="!
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Di 16.11.04 12:59 
Die Theorie mit "erst nach Programmened" hat auch nie gestimmt.. aber spätestens beim Programmende wird der Buffer auf jeden Fall geflushed, insofern kommt man also leicht zu diesem (falschen) Schluss..

Es sollen ja auch die geschriebenen Daten aus dem Zwischenpuffer geflushed werden -> schonmal probiert das Write-Handle zu übergeben? BTW:
PSDK hat folgendes geschrieben:
Anonymous pipes are implemented using a named pipe with a unique name. Therefore, you can often pass a handle to an anonymous pipe to a function that requires a handle to a named pipe.

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
.Chef Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1112



BeitragVerfasst: Di 16.11.04 13:33 
Motzi hat folgendes geschrieben:
Es sollen ja auch die geschriebenen Daten aus dem Zwischenpuffer geflushed werden

Um das nochmal kurz zu verdeutlichen: Ich habe streng genommen zwei Pipes, eine für die Ausgabe und eine für die Eingabe.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
if CreatePipe(StdOutRead,StdOutWrite,@Security,0then
  if CreatePipe(StdInRead,StdInWrite,@Security,0then
  begin
    with StartInfo do
    begin
      cb:=SizeOf(StartInfo);
      hStdInput:=StdInRead;
      hStdOutput:=StdOutWrite;

StdInRead und StdOutWrite sind damit die Pipe-Enden auf der "anderen" Seite, und ich nutze auf "meiner" Seite StdOutRead zum Lesen und StdInWrite zur Eingabe.

Motzi hat folgendes geschrieben:
-> schonmal probiert das Write-Handle zu übergeben?

Ich habe natürlich schon alle Handles auf Teufel-komm-raus geflusht. Bei keinem passiert irgendetwas, außer bei StdOutWrite, da bleibt das Programm hängen. :shock:

Motzi hat folgendes geschrieben:
BTW:
PSDK hat folgendes geschrieben:
Anonymous pipes are implemented using a named pipe with a unique name. Therefore, you can often pass a handle to an anonymous pipe to a function that requires a handle to a named pipe.

Was ich daran noch nicht durchschaut habe ist folgendes: Im MSDN-Beispiel von oben wird das Handle der Named Pipe übergeben, was man bei CreateNamedPipe zurückbekommt. Bei der anonymen Pipe habe ich ja nur meine seperaten Lese- und Schreibhandles, aber kein globales Pipe-Handle. Also was nehmen? :gruebel:

_________________
Die Antworten auf die 5 häufigsten Fragen:
1. Copy(), Pos(), Length() --- 2. DoubleBuffered:=True; --- 3. Application.ProcessMessages bzw. TThread --- 4. ShellExecute() --- 5. Keine Vergleiche von Real-Typen mit "="!
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Di 16.11.04 19:28 
Erzeug einfach nur ein einziges Handle mit Lese- UND Schreibzugriff- und übergebe dieses dann.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
.Chef Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1112



BeitragVerfasst: Fr 19.11.04 11:34 
BenBE hat folgendes geschrieben:
Erzeug einfach nur ein einziges Handle mit Lese- UND Schreibzugriff- und übergebe dieses dann.

Wie soll das dann aussehen? Ich krieg ja schon Probleme beim PeekNamedPipe, wenn ich nur eine Pipe verwende. Und dann nur ein Handle? :shock:

_________________
Die Antworten auf die 5 häufigsten Fragen:
1. Copy(), Pos(), Length() --- 2. DoubleBuffered:=True; --- 3. Application.ProcessMessages bzw. TThread --- 4. ShellExecute() --- 5. Keine Vergleiche von Real-Typen mit "="!
.Chef Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1112



BeitragVerfasst: Di 23.11.04 16:41 
Kurzes Update des Entwicklungsstandes (im Moment wieder Zeitknappheit):

- Also mit einem Handle kireg ich das nicht zm laufen, wie auch immer du das meinst.
- Das Problem tritt nur auf bei Konsolenprogrammen mit längeren Eingaben (z.B. programmiert mit ReadLn). Bei Ein-Buchstaben-Eingaben (z.B. bei XCOPY) gehts so wie von mir gewünscht.

_________________
Die Antworten auf die 5 häufigsten Fragen:
1. Copy(), Pos(), Length() --- 2. DoubleBuffered:=True; --- 3. Application.ProcessMessages bzw. TThread --- 4. ShellExecute() --- 5. Keine Vergleiche von Real-Typen mit "="!