RunProgram und ReadProgramString will nicht funktionieren

Windowsspezifisches Forum , API ,..
Beiträge, die plattformübergreifend sind, gehören ins 'Allgemein'-Forum.
Beefi
Beiträge: 88
Registriert: 16.01.2017 17:38

RunProgram und ReadProgramString will nicht funktionieren

Beitrag von Beefi »

Hi liebe Forengemeinde,

ich lese schon eine Weile mit und habe mich jetzt frisch angemeldet. Ich nutze PureBasic seit etwa einem Jahr und finde es einfach genial...leider stehe ich jetzt vor einem für mich unlösbarem Problem und hoffe, dass ihr mir weiterhelfen könnt :)

Und zwar geht es um die Prozedur RunProgram() im Zusammenhang mit ReadProgramString().
Ich versuche den Output eines Konsolenprogramms auszulesen. Das funktioniert aber einfach nicht...es kommt absolut nichts in meinem PureBasic-Programm an.
Es handelt sich um "ArgyllCMS", eine Softwaresammlung für Farbmanagement (Bildbearbeitung, usw). In dem Paket sind lauter EXE-Dateien, die eine spezielle Funktion haben. Aber ich kann von keinem die Konsolenausgabe einlesen. Beim Programm "Ping" funktioniert es jedoch.

Hier mein Code zum Testen:

Code: Alles auswählen

Define TestProg.i = RunProgram("C:\Diverses\Argyll_V1.9.2\bin\colprof.exe", "", GetTemporaryDirectory(), #PB_Program_Open | #PB_Program_Read)
Text.s

While ProgramRunning(TestProg)
  Text = ReadProgramString(TestProg)
  Debug Text
Wend
ProgramRunning() wartet ja eigentlich, bis alle Konsolenausgaben eingelesen wurden, auch wenn das eigentliche Programm schon beendet ist. Aber das Debugging zeigt, dass das Konsolenprogramm gar nicht läuft. Auch wenn ich im Code die Funktion AvailableProgramOutput() nutze, wird diese einfach übersprungen, weil eben kein Output empfangen wird.
Ersetze ich das Konsolenprogramm "colprof.exe" durch "ping", funktioniert es einwandfrei.

Getestet habe ich es bisher mit PureBasic 32-Bit und 64-Bit. Ebenso jeweils mit ArgyllCMS 32-Bit und 64-Bit. Ich nutze Win 7 64-Bit.
Bisher habe ich das Problem umgangen, indem ich die Konsolenausgabe in eine Datei umgeleitet habe und diese dann ausgelesen habe...aber das ist eine Pfusch-Lösung :mrgreen:

Falls es jemand testen möchte, das Programm ist OpenSource und kann hier heruntergeladen werden:
http://www.argyllcms.com/downloadwin.html
Die EXE's sind alle im darin enthaltenen BIN-Ordner.

Vielleicht hilft das noch zur Fehlersuche...
Wenn ich das Programm "Ping" einlese, werden ja die Umlaute nicht richtig dargestellt.
Eine Umwandlung des Strings mit der Funktion OemToChar_() hat ebenfalls keine Auswirkung...die Umlaute bleiben falsch.

Hat jemand einen Rat?
Ich bin mit meinem Latein leider am Ende :(
Beefi
Beiträge: 88
Registriert: 16.01.2017 17:38

Re: RunProgram und ReadProgramString will nicht funktioniere

Beitrag von Beefi »

Jetzt hab ich doch noch einen Beitrag gefunden, der mein Problem lösen konnte. Erst ewig gesucht und nach dem Post gefunden :oops:

Das Problem konnte gelöst werden, indem ich stderr anstatt stdout auslese. Da muss man erstmal drauf kommen :)
Geholfen hat mir dieser Beitrag: http://purebasic.fr/german/viewtopic.ph ... gramstring

Die Ausgabe von net.exe kann man jedoch auf beide Arten nicht auslesen.


Der Code muss also so aussehen:

Code: Alles auswählen

Define TestProg.i = RunProgram("C:\Diverses\Argyll_V1.9.2\bin\colprof.exe", "", GetTemporaryDirectory(), #PB_Program_Open | #PB_Program_Read | #PB_Program_Error)
Text.s

While ProgramRunning(TestProg)
  Text = ReadProgramError(TestProg)
  Debug Text
Wend
:allright:

__________________________________________________
Domain angepasst
17.01.2017
RSBasic
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: RunProgram und ReadProgramString will nicht funktioniere

Beitrag von ccode_new »

Die Ausgabe von net.exe kann man jedoch auf beide Arten nicht auslesen.
Was für eine net.exe meinst den du? Die in diesem Ordner: C:\Windows\System32\ ?

Diese kann ich mit ReadProgramError() auslesen.
Du musst bei der Debug-Ausgabe nur sehr viel Scrollen.
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Beefi
Beiträge: 88
Registriert: 16.01.2017 17:38

Re: RunProgram und ReadProgramString will nicht funktioniere

Beitrag von Beefi »

Hi ccode_new,

tut mir leid, dass ich jetzt erst antworte.
Ja genau, die im System32 Ordner...man muss ja keinen Ordner mit angeben, "net" genügt.
Ich habe die Tage noch ein wenig rumprobiert und bin auf sämtliche Probleme gestoßen...

Also die Dinge mit ReadProgramString() funktionieren einwandfrei. Viele Programme muss man jedoch über ReadProgramError() auslesen.
Ich bekomme hier ständig Speicherzugriffsfehler direkt von der Funktion ReadProgramError()...und wenn ich diese Fehler nicht bekomme, stürzt das Programm unerwartet bei dieser Funktion ab.
Jetzt habe ich herausgefunden, dass ich mit einer kleinen Pause vor dieser Funktion keine Probleme habe (Beispiel im Code).

Code: Alles auswählen

OpenConsole()

Define TestProg.i = RunProgram("net", "", "", #PB_Program_Open | #PB_Program_Read | #PB_Program_Error)
Define Text1.s
Define Text2.s


While ProgramRunning(TestProg)
  Delay(100) ;Kommentiert man diese Pause aus, stürzt das Programm ab
  Text1 = ReadProgramError(TestProg, #PB_Unicode)
  Text2 = Space(Len(Text1))
  OemToChar_(Text1, Text2)
  PrintN(Text2)
  Debug Text2
Wend

Input()
CloseConsole()
Dass ich OemToChar_() mit zwei unterschiedlichen Variablen nutze, hat den Grund, weil die Funktion sonst nicht mit Unicode funktioniert. Und, dass ich das Program mit Unicode auslese, hat den Grund, weil sonst OemToChar_() nicht funktioniert :)
Hast du einen Tip, wie man das mit der Pause eleganter lösen könnte? Bei Programmen, die über StdOut ausgeben, habe ich keine Probleme, da die Funktion ReadProgramString() ja wartet, bis eine neue Ausgabe vorhanden ist. Zudem kann man mit AvailableProgramOutput() prüfen.
ReadProgrammError() wartet jedoch nicht, bis eine Ausgabe vorhanden ist und AvailableProgramOutput() spricht auf die StdErr auch nicht an.
Ich vermute einfach, dass durch das schnelle abrufen von StdErr (obwohl nichts vorhanden ist) eine Endlosschleife in Erscheinung tritt und sich deshalb das Programm verabschiedet.
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: RunProgram und ReadProgramString will nicht funktioniere

Beitrag von ccode_new »

Hallo Beefi,

warum liest du die Programmausgabe in "Unicode" aus?

Bei mir gibt das "net.exe"-Programm eine "Ascii"-Zeichenkette zurück.

Dein Programm ist ohne das Delay einfach zu schnell fertig.
Da wartet ja NIX auf die Programmausgabe.

Also so funktionierts bei mir:

Code: Alles auswählen

OpenConsole()

Define TestProg.i = RunProgram("net", "", "", #PB_Program_Open | #PB_Program_Read | #PB_Program_Error)
Define Text1.s

While ProgramRunning(TestProg)
  ;Delay(100) ;Hier stürzt bei mir nichts ab!!!
  Repeat
    Text1 = ReadProgramError(TestProg, #PB_Ascii)
  Until Len(Text1) > 0
  PrintN(Text1)
  Debug Text1
Wend

Input()
CloseConsole()
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Beefi
Beiträge: 88
Registriert: 16.01.2017 17:38

Re: RunProgram und ReadProgramString will nicht funktioniere

Beitrag von Beefi »

warum liest du die Programmausgabe in "Unicode" aus?
Weil die Funktion OemToChar_() nur mit Unicode funktioniert (bei mir zumindest).
Ascii funktioniert auch einwandfrei, aber bei Umlauten kommen dann nur komische Zeichen :)

Dein Code funktioniert auf Anhieb. Ändere ich das ganze in Unicode um, dann gibts wieder Probleme (außer ich mach das Delay rein).
Mit diesem Code hier z.B.:

Code: Alles auswählen

OpenConsole()

Define TestProg.i = RunProgram("net", "", "", #PB_Program_Open | #PB_Program_Read | #PB_Program_Error)
Define Text1.s
Define Text2.s


While ProgramRunning(TestProg)
  ;Delay(100) ;Kommentiert man diese Pause aus, stürzt das Programm ab
  Repeat
    Text1 = ReadProgramError(TestProg, #PB_Unicode)
  Until Len(Text1) > 0
  Text2 = Space(Len(Text1))
  OemToChar_(Text1, Text2)
  PrintN(Text2)
  Debug Text2
Wend

Input()
CloseConsole()
In diesem Fall macht es nichts aus, weil die Ausgabe eh Englisch ist...aber ich würde das allgemein gern verstehen, was ich hier falsch mache :(
Du kannst ja mal StdOut von "ping" auslesen...da wirst du gleich merken was ich mit dem Unicode und OemToChar_() meine. Da nimmt man aber ReadProgramString(), wo es sowieso keine Probleme gibt :)
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: RunProgram und ReadProgramString will nicht funktioniere

Beitrag von ccode_new »

Wie gesagt du liest keinen "Unicode" aus.

Die Funktion "OemToChar_()" ist sinnfrei und bringt das Programm nur zum Absturz.

Versuch mal folgenden Code:

Hier kannst du nach der "While-Schleife" auch fortfahren.

Code: Alles auswählen

OpenConsole()

Define TestProg.i = RunProgram("net", "", "", #PB_Program_Open | #PB_Program_Read | #PB_Program_Error)
Global Text1.s
Global Text2.s

While ProgramRunning(TestProg)
  ;Delay(100) ;Kommentiere mich ja nicht aus!!!
  Text1 = ReadProgramError(TestProg, #PB_UTF8)
  If Text1 <> ""
    Text2 = Space(Len(Text1))
    ;OemToChar_(Text1, Text2)
    PrintN((Text1))
  EndIf
Wend
CloseProgram(TestProg)
Input()
CloseConsole()
Die wichtigsten Zeichensätze und -kodierungen

Der in Westeuropa am meisten genutzte Zeichensatz ist ISO 8859-1 (auch „Latin 1“ genannt), der genau wie die anderen Zeichensätze der ISO-8859-Familie auf einer einfachen 8-Bit-Kodierung basiert und somit 28 Zeichen abbilden kann. Der ISO-8895-1-Zeichensatz ist vor allem deshalb so beliebt, da er neben den grundlegenden ASCII-Zeichen auch die fürs Deutsche wichtige Umlaute umfasst; also ä, ö, ü, Ä, Ö, Ü und ß. Somit kommen Sie für deutsche Texte mit diesem Zeichensatz eigentlich aus. Möchten Sie gleichzeitig Zeichen einer anderen Sprache oder eines anderen Zeichensystems nutzen, reicht dieser Zeichensatz nicht mehr aus.

Also wurde Unicode erfunden, der mit derzeit 220+216 möglichen Zeichen langfristig jedes sinntragende Zeichen beziehungsweise Textelement aller bekannten Schriftkulturen und Zeichensysteme umfassen soll. Die gebräuchlichste Kodierung für Unicode-Daten ist UTF-8, bei der ein geschickter Trick angewandt wird: denn reicht ein Byte zur Abbildung des Zeichens nicht aus, wird einfach ein zweites Byte dazu genommen; reicht auch das nicht aus, wird ein weiteres Byte dazu genommen und so weiter.
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Beefi
Beiträge: 88
Registriert: 16.01.2017 17:38

Re: RunProgram und ReadProgramString will nicht funktioniere

Beitrag von Beefi »

Hi ccode_new,

erstmal vielen Dank für deine Hilfe. Ich hab da noch ein paar Fragen zu deinem Code...
Warum hast du hier jetzt UTF8 anstatt Unicode oder Ascii verwendet?
Und bringt die Funktion CloseProgram(TestProg) nach der While-Schleife eigentlich nochwas? Die Schleife wird doch eh erst verlassen, wenn das Programm "TestProg" geschlossen ist, oder nicht?

Der Code funktioniert, jedoch habe ich hier wieder das Problem mit den Umlauten :)

Ich gebe mal ein anderes Beispiel (nicht mit StdErr, sondern mit StdOut):

Code: Alles auswählen

OpenConsole()

Define TestProg.i = RunProgram("ping", "", "", #PB_Program_Open | #PB_Program_Read | #PB_Program_Error)
Global Text1.s


While ProgramRunning(TestProg)
  Text1 = ReadProgramString(TestProg)
  If Not Text1 = ""
    PrintN((Text1))
  EndIf
Wend

Input()
CloseConsole()
...bei diesem Code wird die Ausgabe von "Ping" gezeigt. Hier sieht man gleich in der ersten Zeile, dass das Wort "Größe" als "Gr??e" ausgegeben wird.
Um dieses Problem zu umgehen, muss man den String mit OemToChar_() umwandeln.
Hier ein Beispiel, wie es funktioniert:

Code: Alles auswählen

OpenConsole()

Define TestProg.i = RunProgram("ping", "", "", #PB_Program_Open | #PB_Program_Read | #PB_Program_Error)
Global Text1.s
Global Text2.s

While ProgramRunning(TestProg)
  Text1 = ReadProgramString(TestProg, #PB_Unicode)
  If Not Text1 = ""
    Text2 = Space(Len(Text1))
    OemToChar_(Text1, Text2)
    PrintN((Text2))
  EndIf
Wend

Input()
CloseConsole()
Hier ist alles paletti mit den Umlauten. Und genau das gleiche habe ich eben mit der Funktion ReadProgramError (anstatt ...String) vor.
Aber da ReadProgramError() nicht wartet, stürzt das ganze Programm irgendwie ab...außer mit Delay() :mrgreen:
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: RunProgram und ReadProgramString will nicht funktioniere

Beitrag von ts-soft »

Hier steht doch schon die Lösung!
Hier nochmal zusammengefaßt:

Code: Alles auswählen

EnableExplicit

OpenConsole()

Define TestProg.i = RunProgram("ping", "", "", #PB_Program_Open | #PB_Program_Read | #PB_Program_Error)
Global Text1.s

While ProgramRunning(TestProg)
  Text1 = ReadProgramString(TestProg, #PB_UTF8)
  PrintN((Text1))
Wend
CloseProgram(TestProg)
Input()
CloseConsole() 
Es gibt keinen OEM-Text! Das schließen des Programms ist auch notwendig um Speicherlecks zu vermeiden, siehe Hilfe!
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Beefi
Beiträge: 88
Registriert: 16.01.2017 17:38

Re: RunProgram und ReadProgramString will nicht funktioniere

Beitrag von Beefi »

Hi ts-soft,

hab gerade mal deinen Code ausgeführt. Hier ein Screenshot von meinem Ergebnis:

Bild

...die Umlaute werden alle noch falsch dargestellt. Liegt der Fehler vielleicht an einer anderen Einstellung?

Es gibt keinen OEM-Text!
Die Funktion OemToChar_() wird hier im Forum häufig für solche Angelegenheiten verwendet...unter anderem von dir :)
Ich habe das einfach so übernommen.
Antworten