Mit WriteProgramString() Strg+c senden

Anfängerfragen zum Programmieren mit PureBasic.
jogo
Beiträge: 135
Registriert: 22.11.2020 20:05
Computerausstattung: 'ne Handvoll gebrauchte Laptops & PCs mit Mint und LMDE

Mit WriteProgramString() Strg+c senden

Beitrag von jogo »

ich finde keine Möglichkeit, ein Kommandozeilenprogramm welches ich mit RunProgram() gestartet habe, über WriteProgramString() mit Strg+c zu beenden.
Oder ist dafür KillProgram() gedacht? Hab Sorge, dass dieses Programm vllt. nicht richtig abschließen kann, wenn es "gekillt" wird. Sendet KillProgram() denn zum ZielProgramm einfach nur den Befehl zum Beenden (zB. Strg+c) oder wird es "brutal abgeschossen"?

PS:
Der offizielle Befehl zum Beenden ist Strg+c, wenn man es im Terminal startet.
--
Ideen gibt es viele - man muss sie nur haben...
Mint / LMDE5+6 // PureBasic 6.21
Benutzeravatar
mk-soft
Beiträge: 3869
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Mit WriteProgramString() Strg+c senden

Beitrag von mk-soft »

PB Hilfe:
Wenn das Programm mit dem #PB_Program_Write Flag gestartet wurde, veranlasst CloseProgram() das Programm, ein 'EOF' (Ende der Datei) auf seiner Standardeingabe zu empfangen. Diese Bedingung kann auch "produziert" werden, ohne die Verbindung zum Programm zu schließen, indem WriteProgramData() mit dem speziellen #PB_Program_Eof Wert aufgerufen wird.

Code: Alles auswählen

cmd = RunProgram("cmd", "", "", #PB_Program_Open | #PB_Program_Read | #PB_Program_Write)
If cmd
  Delay(1000)
  WriteProgramData(cmd, #PB_Program_Eof, 0)
  If WaitProgram(cmd, 1000) = 0
    Debug "Kill"
    KillProgram(cmd)
  EndIf
EndIf
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8820
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Mit WriteProgramString() Strg+c senden

Beitrag von NicTheQuick »

Hm, es wäre eigentlich schon cool, wenn man bei `KillProgram()` auch die entsprechende Signale mitgeben könnte, die so möglich sind. Aber ich schätze das unterscheidet sich dann stark von Betriebssystem zu Betriebssystem und wäre deshalb nicht so leicht zu vereinheitlichen.
jogo
Beiträge: 135
Registriert: 22.11.2020 20:05
Computerausstattung: 'ne Handvoll gebrauchte Laptops & PCs mit Mint und LMDE

Re: Mit WriteProgramString() Strg+c senden

Beitrag von jogo »

ich bau das mit WriteProgramData(cmd, #PB_Program_Eof, 0) gleich mal - aktuell läuft grad ein Test, den ich nicht abbrechen will ;)
Ich befürchte jedoch, das dieses Programm (pw-record) sich nicht durch EOF beenden wird, weil es ja auf Strg+c wartet. Aber mal sehen..
Hilfreich wäre, wenn man über WriteProgramString() oder WriteProgramData() Tastenkombinationen senden könnte, also solche Konstanten wie bei AddKeyboardShortcut().
@NicTheQuick, meinst du die Tastenkombis mit KillProgram() gleich mitschicken? Ich weiß ja auch nicht, was KillProgramm() genau macht. Vllt. schickt es ja einen Standard-Beenden Befehl zB. Strg+c an das Programm. Aber das wär natürlich gut, wenn man das durch einen weiteren Parameter mitschicken könnte, falls es mal abweicht oder speziell wird.

PS: die Seite hier reagiert aktuell sehr langsam - läuft da was im Hintergrund?
--
Ideen gibt es viele - man muss sie nur haben...
Mint / LMDE5+6 // PureBasic 6.21
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8820
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Mit WriteProgramString() Strg+c senden

Beitrag von NicTheQuick »

Erst mal muss man verstehen, dass Daten senden nicht direkt etwas mit den Tastenkombinationen zu tun hat, die man aus dem Terminal kennt. STRG+C wird nicht als Zeichen an den Standard-Input des Programms gesendet, sondern schon davor vom tty-Treiber interpretiert und in ein Signal umgewandelt. In Fall von STRG+C wird es zu SIGINT. Es wäre sehr unpraktisch, wenn man solche Signale per stdin ans Programm übergeben könnte, da das dann die Möglichkeit Binärdaten zu streamen ausschließen würde.

Man kann sich unter Linux im Terminal mit `stty -a` ausgeben lassen welche Key-Bindings welche Signale verursachen. Bei mir sind es diese hier:

Code: Alles auswählen

$ stty -a
speed 38400 baud; rows 43; columns 190; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; discard = ^O;
min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke -flusho -extproc
Jetzt sind die aber leider nicht so ohne weiteres lesbar. Die Zeichenfolge ^C steht normalerweise für STRG+C, das selbe gilt für ^U (STRG+U) oder ^D (STRG+D). Eine Zuordnung in menschenlesbarer Form habe ich mir mal von ChatGPT erstellen lassen. Das kam dabei raus:

Code: Alles auswählen

STRG+C   SIGINT       Unterbricht den aktuellen Prozess  
STRG+\   SIGQUIT      Beendet Prozess und erzeugt Core-Dump  
ENTF     ERASE        Löscht vorheriges Zeichen  
STRG+U   KILL         Löscht gesamte Eingabezeile  
STRG+D   EOF          Sendet End-of-File (Beendet Eingabe)  
STRG+Q   START        Setzt gestoppten Output fort  
STRG+S   STOP         Hält Terminal-Output an (Flow Control)  
STRG+Z   SIGTSTP      Stoppt (pausiert) Prozess  
STRG+R   RPRNT        Druckt aktuelle Eingabezeile neu  
STRG+W   WERASE       Löscht letztes Wort  
STRG+V   LNEXT        Nächstes Zeichen wörtlich eingeben  
STRG+O   DISCARD      Verwirft (pausiert) Output bis nächste Eingabe  
Und wenn du ein solches Signal an einen Prozess senden möchtest, nutze `kill_()`. Hier ein Beispiel anhand von `ping`:

Code: Alles auswählen

Enumeration Signals
	#SIGINT = 2
EndEnumeration

Define timeout = 5000

Define output.s, time_end.i

hProcess.i = RunProgram("ping", "127.0.0.1", "", #PB_Program_Open | #PB_Program_Read | #PB_Program_Write | #PB_Program_Error | #PB_Program_UTF8)
If hProcess
	time_end = ElapsedMilliseconds() + timeout
	If ProgramRunning(hProcess)
		pid.i = ProgramID(hProcess)
		Debug pid
		
		While ProgramRunning(hProcess)
			If AvailableProgramOutput(hProcess)
				Debug ReadProgramString(hProcess)
			EndIf
			error.s = ReadProgramError(hProcess)
			If error
				Debug error
			EndIf
			If ElapsedMilliseconds() > time_end
				kill_(pid, #SIGINT)
			EndIf
		Wend
		
		Debug "Beendet"
	EndIf
EndIf
jogo
Beiträge: 135
Registriert: 22.11.2020 20:05
Computerausstattung: 'ne Handvoll gebrauchte Laptops & PCs mit Mint und LMDE

Re: Mit WriteProgramString() Strg+c senden

Beitrag von jogo »

Danke, mit deiner Lösung konnte ich das Programm regulär beenden und es hat seine Arbeit vorher zuende "geschrieben".
Mit KillProgram() ging das schief und die erzeugte Datei war nicht korrekt.
Frage zum Verständnis:
Wo hast du jetzt hergeleitet, dass #SIGINT den Wert 2 haben muß, damit Strg+C gesendet wird?
Aus der Ausgabe mit `stty -a` geht das ja auch nicht hervor. Ich versteh da den Zusammenhang noch nicht...

@mk-soft: das EOF mit WriteProgramData() hat pw-record nicht beendet. Vermutlich hast du aber was anderes gemeint, oder?
--
Ideen gibt es viele - man muss sie nur haben...
Mint / LMDE5+6 // PureBasic 6.21
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8820
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Mit WriteProgramString() Strg+c senden

Beitrag von NicTheQuick »

Gib im Terminal mal 'kill -l' ein. Das listet dir alle möglichen Signale mit ihren Nummern auf. Das sind immer die gleichen.
jogo
Beiträge: 135
Registriert: 22.11.2020 20:05
Computerausstattung: 'ne Handvoll gebrauchte Laptops & PCs mit Mint und LMDE

Re: Mit WriteProgramString() Strg+c senden

Beitrag von jogo »

Vielen Dank für die Tips - haben mir sehr weiter geholfen. :)
PS:
Übrigens finde ich es interessant, wie du im obigen Beispiel den Timer gebaut hast. Ähnelt dem Vorgehen, wie man mehrere Timer beim Programmieren am Arduino löst :)
--
Ideen gibt es viele - man muss sie nur haben...
Mint / LMDE5+6 // PureBasic 6.21
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8820
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Mit WriteProgramString() Strg+c senden

Beitrag von NicTheQuick »

jogo hat geschrieben: 02.11.2025 01:09Übrigens finde ich es interessant, wie du im obigen Beispiel den Timer gebaut hast. Ähnelt dem Vorgehen, wie man mehrere Timer beim Programmieren am Arduino löst :)
Das solltest du aber nicht als Empfehlung betrachten. So ein Busy Wait ist nicht gerade Resourcen schonend. Eigentlich löst man sowas besser mit Timern, und bei Arduino nutzt man da auch besser Timer mit Interrupts. Aber in diesem Beispiel hab ich mir das der Einfachheit halber gespart.
Antworten