Ich würde gerne für meine Projekte den Zugriff auf externe Konsolenprogramme und das auslesen deren outputs besser gestallten wollen.
Das erstellen eines Threads(damit der TProcess schön unabhängig arbeiten kann)klappt.
Auch habe ich im netz gesucht und man wird sehr oft immer auf bekannte Seite:
http://wiki.lazarus.freepascal.org/Exec ... rograms/de weitergeleitet.
Ich habe mir dann das Beispiel für das lesen eines grossen outputs genommen, leicht angepasst, und siehe da am ende des TProcesses wird der output auch ordentlich angezeigt.
Als erstes mal der Quellcode für den Thread welcher dann den TProcess startet.
Code: Alles auswählen
procedure Tmkvmerge.Execute;
var
mkvmerge_exe: string;
aprocess: TProcess;
READ_BYTES: integer = 2048;
b: LongInt;
BytesRead: LongInt = 0;
// das sind globale variablen
gv_mem_stream - TMemoryStream
gv_mkvmerge_error - String
gv_mkvmerge_paras - String
begin
if (not Terminated) and (true {any condition required}) then
begin
// error code leeren
gv_mkvmerge_error:='';
// prüfen ob die mkvmerge exe vorhanden ist
mkvmerge_exe:=settings.Frm_Settings.DiE_Path_MKVToolNix.Text+ 'mkvmerge.exe';
if FileExists(Utf8ToAnsi(mkvmerge_exe)) then
begin
try
// den memory stream init
gv_mem_stream:=TMemoryStream.Create;
// den process initialisieren
aprocess:=TProcess.Create(nil);
// den process mit der datei verbinden
aprocess.Executable:=Utf8ToAnsi(mkvmerge_exe);
// den output für den process aktivieren
aprocess.Options := aprocess.Options + [poUsePipes];
// den parameter string angeben
aprocess.Parameters.Add(Utf8ToAnsi(gv_mkvmerge_paras));
// den process verstecken
aprocess.ShowWindow:=swoHIDE;
// process starten
aprocess.Execute;
// solange der process andauert
while aprocess.Running do
begin
// stellt sicher, dass wir Platz haben
gv_mem_stream.SetSize(BytesRead + READ_BYTES);
// versuche, es zu lesen
b:=aprocess.Output.Read((gv_mem_stream.Memory + BytesRead)^,READ_BYTES);
if b > 0 then
begin
Inc(BytesRead, b);
//@ hier sollte die Auswertung für real time rein. also immer wenn der output gelesen wurde sofort verarbeiten
// Main Thread - Auswertung des mkvmerge outputs
// Synchronize(@mkvmerge_output_verarbeiten);
end
else
begin
// keine Daten, warte 1 ms
Sleep(1);
end;
end;
// lese den letzten Teil
repeat
// stellt sicher, dass wir Platz haben
gv_mem_stream.SetSize(BytesRead + READ_BYTES);
// versuche es zu lesen
b:=aprocess.Output.Read((gv_mem_stream.Memory + BytesRead)^,READ_BYTES);
if b > 0 then
begin
Inc(BytesRead, b);
end;
until b <= 0;
// die größes des memory-stream einstellen
gv_mem_stream.SetSize(BytesRead);
// Main Thread - Auswertung des mkvmerge outputs
Synchronize(@mkvmerge_output_verarbeiten);
Except
on e: Exception do
begin
gv_mkvmerge_error:='mkvmerge process error';
end;
end;
end
else
// die mkvmerge.exe wurde nicht gefunden
gv_mkvmerge_error:='keine mkvmerge.exe';
// Main Thread - Auswertung des mkvmerge errors
Synchronize(@mkvmerge_error_verarbeiten);
// memory stream frei geben
if Assigned(gv_mem_stream) then
gv_mem_stream.Free;
Terminate;
end;
end;
Wenn ich die Synchronize(@mkvmerge_output_verarbeiten); ausführe an besagter stelle
habe ich am ende eine leere Stringlist/ Memo.
Wird die Synchronize(@mkvmerge_output_verarbeiten); nur am ende ausgeführt habe ich alles vollständig da.
Wie kann ich es erreichen das der output immer direkt gelesen wird und nach und nach in die Stringlist/Memo geschrieben wird.
hubble