Einzelnen Beitrag anzeigen

Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#3

Re: Cmd.exe über Pipes steuern - Probleme

  Alt 9. Apr 2006, 10:42
ich kenn mich mit den Pipes nicht so aus. Allerdings klingt das für mich danach als ob du die Ausgabe erst lesen kannst wenn sie vollständig abgearbeitet ist. Also würde ich vermuten das die Anwendung (cmd.exe) so lange nicht reagiert. Wenn man also Dir ausführt braucht es einen Moment bis die platte durchsucht ist und dann wird alles in den ausgabepuffer geschrieben und in dieser Zeit reagiert das ganze wohl nicht mehr auf ausgaben. Gegen diese Theorie spricht jedoch das man bei der CMD.exe live sieht wie der Inhalt aufgelistet wird wenn man es direkt ausführt und dir eingibt.

Vom Thema los gelöst möchte ich dich bitten den Screenshot als Anhang dem Beitrag hinzu zufügen. Einfach aus dem Grund das der Screenshot auch noch in 3 Jahren vorhanden ist wenn dein Server nicht mehr existiert oder du das bild von deinem Webspace gelöscht hast.

[Edit]
Hab mir grad selbst mal nen kleines Testprogramm mit den Pipes gebaut und konnte deine Beschriebenen Probleme nicht nachvollziehen. Im übrigen hast du geschrieben das bei dir die cmd.exe derzeit immer unter "c:\windows\system32" liegen muss. Gib als command bei CreateProcess doch einfach "cmd" an dann brauchst du dich auch nicht drum kümmern wo die exe liegt.

Was mir an deinem Quelltext negativ aufgefallen ist und gleichzeitig der Grund für das hängen sein kann ist folgende zeile:
MainForm.CLBack(BufferToString(buf)); du scheinst also unsyncronisiert vom Thread auf den Haupttrehad der Anwendung zu zugreifen und gibst dort vermutlich sogar etwas auf der Oberfläche aus. Du solltest das ganze mit syncronize syncronisieren oder per Message an den Hauptthread schicken.

Ich würde dir auch empfehlen das ganze objectorientierter zu machen. Also nicht vom Thread aus auf eine Globale Variable (dein Form) zu zugreifen sondern die CLB-Funktion lieber als Parameter übergeben. Hier mal ein Beispiel wie der Thread aussehen könnte (natürlich mit syncronisierter Benachrichtigung)
Delphi-Quellcode:
type
  TPipeClbProc = procedure(Sender: TObject; const ABuffer: String; ABufSize: Cardinal) of Object;
  TPipeReadThread = class(TThread)
  private
    fBuffer: String;
    fBytesRead: Cardinal;
    fClbProc: TPipeClbProc;
    fPipeOutput: Cardinal;
    procedure FSyncProc;
  protected
    procedure Execute; override;
    constructor Create(AClbProc: TPipeClbProc; APipeOutput: Cardinal);
  end;
[...]
constructor TPipeReadThread.Create(AClbProc: TPipeClbProc; APipeOutput: Cardinal);
begin
  inherited Create(True);
  fClbProc := AClbProc;
  fPipeOutput := APipeOutput;
  SetLength(fBuffer, 5000);
  FreeOnTerminate := True;
  Resume;
end;

procedure TPipeReadThread.Execute;
var LBufSize: Cardinal;
    LRes : Boolean;
begin
  LBufSize := Length(fBuffer);
  repeat
    LRes := ReadFile(fPipeOutput, fBuffer[1], LBufSize, fBytesRead, nil);
    Synchronize(fSyncProc);
  until not(LRes) or Terminated;
end;

procedure TPipeReadThread.FSyncProc;
begin
  fClbProc(Self, fBuffer, fBytesRead);
end;
[/Edit]
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat