(Gelöst)TProcess, Übergabe von Kommandos an Konsolenprogamm

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
Antworten
Frank Ranis
Beiträge: 201
Registriert: Do 24. Jan 2013, 21:22

(Gelöst)TProcess, Übergabe von Kommandos an Konsolenprogamm

Beitrag von Frank Ranis »

Hallo ,

habe ein kleines Problem mit TProcess und der Übergabe von Steuerkommandos an ein Konsolenprogramm.

Worum geht es .

Ich benutze für meine Aerodynamikprogramme öfter mal das Konsolen-Programm XFOIL.
Hiermit kann man die Aerodynamischen Eigenschaften von Flugzeugprofilen berechnen.

Normal wird XFoil gestartet und man steuert es per Handeingaben.
Für eine Automatik per Script habe ich bis dato eine Batch-Datei und ein Sript-Textdatei verwendet.

Beispiel: Start.bat

Code: Alles auswählen

xfoil.exe < script.txt
echo XFoil ist fertig mit rechnen!! > fertig.txt


In der Datei Script.txt stehen dann die Kommandos , die das XFoil steuern .
Und am Ende fällt hinten eine Text-Tabelle mit den Berechneten Werten raus .

Das funktioniert eigentlich Problemlos , es sei denn , das XFoil gerät in ein Koma , hängt sich also weg .
Das passiert nicht sehr oft , aber ab und an doch mal und dann hat man ein Zombie am laufen , unschön.

Die Batch kann man nun auch schön per TProcess starten , funzt tadellos, es sei den XFoil stürtz ab , dann kommt man zwar an den Process heran (das Batchprogramm) aber nicht an die XFoil.exe selber , da das ja ein Prozess ist , den das Batch erzeugt hat .

Code: Alles auswählen

// Start per Batch , alte Vorgehensweise
procedure TForm1.Button1Click(Sender: TObject);
begin
 p:=tprocess.Create(nil);
 P.Options := [poWaitOnExit];
 p.Executable:=pfad+'\start.bat';
 p.Execute;
 freeandnil(p);
end;   
 

------------

Nun dachte ich mir , benutze doch einfach TProcess direct mit der XFoil.exe.
Also zunächst mal die reine XFoil.exe im Process aufgerufen.

Code: Alles auswählen

// Start der reinen XFoil.exe ohne Übergaben
procedure TForm1.Button2Click(Sender: TObject);
begin
 p:=tprocess.Create(nil);
 P.Options := [poWaitOnExit];
 p.Executable:=pfad+'\xfoil.exe';
 p.Execute;
 freeandnil(p);
end;         
 

Funzt , XFoil-Prog wird aufgemacht und ich kann dort meine Kommandos per Hand eingeben (z.B. Quit+Enter zum Verlassen des XFoil).

------------

Diese Procedure dann erweitert mit der Möglichkeit , Textkommados zu übergeben.

Code: Alles auswählen

// Versuch mit Kommando-Übergabe
procedure TForm1.Button3Click(Sender: TObject);
var s:string;
begin
 p:=tprocess.Create(nil);
 P.Options := [poUsePipes];
 p.Executable:=pfad+'\xfoil.exe';
 p.Execute;
 
 // Ab hier sollen dann die Kommandos (siehe Script.txt) gesendet werden
 s:='load NACA4415.DAT';
 p.Input.Write(s,length(s));
 
 sleep(2000);
 
 freeandnil(p);
end;       


Aber nun startet das XFoil nicht mehr .

Klammere ich die Zeile

Code: Alles auswählen

P.Options := [poUsePipes];


aus , wird XFoil zwar ausgeführt , dafür ballert es dann in der Zeile

Code: Alles auswählen

p.Input.Write(s,length(s));



Hat irgend jemand eine Idee , wie man das zum Laufen bekommen kann ?

Der komplette Code im Anhang.

Gruß

Frank
Dateianhänge
Laz_XFoil1.zip
(1.46 MiB) 94-mal heruntergeladen
Zuletzt geändert von Frank Ranis am Fr 7. Jul 2017, 14:26, insgesamt 1-mal geändert.
www.flz-vortex.de

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: TProcess, Problem mit Übergabe von Kommandos an Konsolen

Beitrag von Socke »

Hast du versucht, poWaitOnExit und poUsePipes miteinander zu kombinieren?
Edit: der Vorschlag kann nicht funktionieren, da dein Programm darauf wartet, dass der Prozess fertig ist, bevor es Daten sendet.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Frank Ranis
Beiträge: 201
Registriert: Do 24. Jan 2013, 21:22

Re: TProcess, Problem mit Übergabe von Kommandos an Konsolen

Beitrag von Frank Ranis »

Hi Socke,

Socke hat geschrieben:Hast du versucht, poWaitOnExit und poUsePipes miteinander zu kombinieren?
Edit: der Vorschlag kann nicht funktionieren, da dein Programm darauf wartet, dass der Prozess fertig ist, bevor es Daten sendet.


Nein , in Procedure Button3Click ist die Option 'poWaitOnExit' nicht enthalten.

Gruß

Frank
www.flz-vortex.de

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: TProcess, Problem mit Übergabe von Kommandos an Konsolen

Beitrag von Warf »

Mal so ne ganz dumme Anmerkung, mit

Code: Alles auswählen

s:='load NACA4415.DAT';
 p.Input.Write(s,length(s));

sendest du keinen Newline Character. Wenn das Programm die Informationen Zeile für Zeile einliest, wird es sowiso so lange blockieren bis du einen newline Character schreibst. Also mich würde es definitiv nicht wundern falls du damit einen Deadlock erhälst

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: TProcess, Problem mit Übergabe von Kommandos an Konsolen

Beitrag von Socke »

Jetzt ist mir der Fehler aufgefallen. Die Variable s ist technisch nur ein Pointer auf den String; mit deinem Code schreibst du nur den Pointer und das was danach kommt.
Stattdessen musst du das erste Zeichen aus dem String angeben:

Code: Alles auswählen

s:='load NACA4415.DAT';
 p.Input.Write(s[1],length(s));
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Frank Ranis
Beiträge: 201
Registriert: Do 24. Jan 2013, 21:22

Problem gelöst

Beitrag von Frank Ranis »

Hallo Socke,

Socke hat geschrieben:Jetzt ist mir der Fehler aufgefallen. Die Variable s ist technisch nur ein Pointer auf den String; mit deinem Code schreibst du nur den Pointer und das was danach kommt.
Stattdessen musst du das erste Zeichen aus dem String angeben:

Code: Alles auswählen

s:='load NACA4415.DAT';
 p.Input.Write(s[1],length(s));


Ja , habe ich auch entdeckt , danke für den Hinweis.

Habe jetzt folgendes herausgefunden:

Benutzt man die

Code: Alles auswählen

P.Options := [poUsePipes] 

wird sämtliche Ein/Ausgabe in die Konsole vom Prozess abgefangen.

Und weil da keine Anzeige kam , hat mich das stutzig gemacht.

Man muß sich die Informationen halt selber holen .
Somit ist auch eine Anzeige der Konsole unnütz und man kann diese gleich mit abschalten.
Also

Code: Alles auswählen

P.Options := [poUsePipes,poNoConsole]; 


Im Anhang noch das funktionierende Projekt , wenn es jemanden interessiert.

Muß nur noch alles in einen separten Thread packen , damit das Hauptprogramm aktiv bleibt .

Ich danke euch trotzdem .

Gruß

Frank
Dateianhänge
Laz_XFoil2.zip
(1.47 MiB) 109-mal heruntergeladen
www.flz-vortex.de

braunbär
Beiträge: 369
Registriert: Do 8. Jun 2017, 18:21
OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10, FPC 3.2.0
CPU-Target: 64Bit
Wohnort: Wien

Re: (Gelöst)TProcess, Übergabe von Kommandos an Konsolenprog

Beitrag von braunbär »

Ein Hinweis zu deinem Programm:

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
begin
 pfad:=extractfiledir(paramstr(0));
end;
 



Lazarus-Hilfe hat geschrieben:In general, it's a bad idea to rely on the location of the binary. Often, this goes against best OS practices. Configuration data should (or can) not be stored next to the binary, but on designated locations. What locations these are, is very much operating system dependent. Therefore, ParamStr(0) should be used with care.


FAst immer ist es m.E. besser, GetCurrentDir zu verwenden. Das liefert dir das aktuelle Arbeitsverzeichnis, unabhängig davon, aus welchem Verzeichnis das Programm gestartet wurde. Wenn man eine Programmverknüpfung erstellt, ist das Arbeitsverzeichnis ohnedies standardmäßig das Programmverzeichis, aber das kann man in der Verknüpfung eben ändern, wenn man will. Normalerweise ist es für das laufende Programm egal, in welchem Verzeichnis das Exe-File steht (außer, man will - unter Windows - eine DLL aus dem Programmverzeichnis laden, oder dergleichen), wichtig ist, wenn schon, das Arbeitsverzeichnis.

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: (Gelöst)TProcess, Übergabe von Kommandos an Konsolenprog

Beitrag von m.fuchs »

braunbär hat geschrieben:

Code: Alles auswählen

 pfad:=extractfiledir(paramstr(0))


FAst immer ist es m.E. besser, GetCurrentDir zu verwenden. Das liefert dir das aktuelle Arbeitsverzeichnis, unabhängig davon, aus welchem Verzeichnis das Programm gestartet wurde.

Das nützt dem OP aber gar nichts, schadet nur. Er geht ja davon aus dass xfoil.exe im gleichen Verzeichnis wie sein eigenes Programm liegt. Dafür braucht er den Pfad. Benutzt er nun GetCurrentDir und das Programm wird aus einem anderen Verzeichnis gestartet, dann wird xfoil.exe nicht mehr gefunden.

ParamStr(0) und GetCurrentDir sind nicht synonym.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

braunbär
Beiträge: 369
Registriert: Do 8. Jun 2017, 18:21
OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10, FPC 3.2.0
CPU-Target: 64Bit
Wohnort: Wien

Re: (Gelöst)TProcess, Übergabe von Kommandos an Konsolenprog

Beitrag von braunbär »

Ja, du hast Recht. Mir ist das paramStr(0) ins Auge gesprungen, was man normalerweise bleiben lassen (oder zumindest einen kurzen erklärenden Kommentar dazu schreiben) sollte, genauer habe ich mir dann nicht angeschaut, was das Programm damit macht.

Dein belehrendes "ParamStr(0) und GetCurrentDir sind nicht synonym." hättest du dir allerdings sparen können, weil wenn die synonym wären, dann wäre mein Kommentar sowieso obsolet.

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: (Gelöst)TProcess, Übergabe von Kommandos an Konsolenprog

Beitrag von wp_xyz »

braunbär hat geschrieben:Dein belehrendes "ParamStr(0) und GetCurrentDir sind nicht synonym." hättest du dir allerdings sparen können...

Nicht schon wieder! Jeder, der hier etwas antwortet, ist irgendwie "belehrend". Bitte spare dir solche stichelnde Attribute.

Antworten