Im ersten Teil haben wir die Ausgabe von ver mit > in eine Datei geschickt und sie aus VFP gelesen. Hier kommt, was dahintersteckt: wo ein Konsolenprogramm schreibt und liest, wie man jedes davon umleitet und wie ein Programm dem, der es gestartet hat, sagt, ob es gut gelaufen ist. Damit können Sie Programme verketten und in einer .bat benutzen, ohne auf den Bildschirm zu schauen.
Drei Kanäle
Jedes Konsolenprogramm startet mit drei offenen Kanälen:
| Kanal | Name | Wofür |
|---|---|---|
| Eingabe | stdin | was das Programm liest (die Tastatur, wenn Sie nichts anderes sagen) |
| Ausgabe | stdout | das Ergebnis |
| Fehler | stderr | Warnungen und Fehler |
Ausgabe und Fehler landen auf demselben Bildschirm, also sieht man auf den ersten Blick keinen Unterschied. Es sind zwei verschiedene Kanäle, und man kann sie an verschiedene Orte schicken.
VFP hat etwas Ähnliches für die Ausgabe. Was Sie mit ? schreiben, geht auf den Bildschirm, und mit SET ALTERNATE schicken Sie es zusätzlich in eine Datei:
SET ALTERNATE TO echo.txt
SET ALTERNATE ON
? "Offene Rechnungen:", 12
SET ALTERNATE OFF
SET ALTERNATE TOIn echo.txt steht dann Offene Rechnungen: 12. Was VFP nicht hat, ist ein eigener Kanal für Fehler: Ein VFP-Fehler öffnet ein Fenster oder springt in Ihr ON ERROR.
Die Ausgabe in eine Datei
> schickt die Ausgabe in eine Datei statt auf den Bildschirm. Gibt es die Datei schon, wird sie ersetzt:
ping -n 1 127.0.0.1 > ausgabe.txtAuf dem Bildschirm erscheint nichts, und ausgabe.txt enthält die 9 Zeilen, die Sie gesehen hätten. Mit >> wird angehängt statt ersetzt: noch ein ping -n 1 127.0.0.1 >> ausgabe.txt, und die Datei hat 18 Zeilen.
Wenn Sie die Ausgabe nicht interessiert, schicken Sie sie nach nul, einer besonderen Windows-Datei, die alles verschluckt:
ping -n 1 127.0.0.1 > nulFehler gehen einen anderen Weg
Schicken Sie einmal die Ausgabe eines Git-Unterbefehls, den es nicht gibt, in eine Datei:
git estado > ergebnis.txtgit: 'estado' is not a git command. See 'git --help'.Die Meldung erscheint trotzdem auf dem Bildschirm, und ergebnis.txt bleibt leer, 0 Bytes. Git hat die Meldung über den Fehlerkanal geschrieben, und > leitet nur die Ausgabe um. Für den Fehler setzt man eine 2 davor:
git estado 2> fehler.txtJetzt bleibt der Bildschirm leer, und die Meldung steht in fehler.txt. Wollen Sie beides in derselben Datei, schickt 2>&1 den Fehler dorthin, wohin die Ausgabe geht:
git estado > alles.txt 2>&1Dafür sind zwei Kanäle gut: Sie speichern das Ergebnis in einer Datei, und Probleme erscheinen weiter auf dem Bildschirm oder in einer anderen Datei, ohne sich mit den Daten zu vermischen. Schreibt ein Programm JSON auf die Ausgabe und seine Warnungen auf den Fehlerkanal, kommt das JSON sauber heraus.
Nicht jedes Programm hält sich daran. ping schreibt seine eigenen Fehler auf die normale Ausgabe: ping -n 127.0.0.1 > p.txt zeigt nichts, und die Fehlermeldung (bei mir „Debe especificar la dirección IP.“) landet in p.txt. Wenn ein Fehler nicht dort auftaucht, wo Sie ihn erwarten, sehen Sie auch in der Ausgabedatei nach.
Die Eingabe aus einer Datei
< macht das Gegenteil von >: Das Programm liest aus einer Datei statt von der Tastatur. sort sortiert die Zeilen, die über die Eingabe ankommen:
sort < staedte.txtAlmeria
Madrid
ZaragozaTippen Sie sort allein, wartet es darauf, dass Sie Zeilen eingeben, weil seine Eingabe die Tastatur ist. Viele Konsolenprogramme arbeiten so: Sie lesen ihre Eingabe, verarbeiten sie und schreiben das Ergebnis.
Die Pipe: die Ausgabe des einen in die Eingabe des anderen
Der senkrechte Strich | verbindet zwei Programme: Was das erste auf seine Ausgabe schreibt, kommt beim zweiten über die Eingabe an, ohne Umweg über eine Datei. tasklist listet die laufenden Prozesse auf, und find behält die Zeilen, die einen Text enthalten. Mit geöffnetem VFP:
tasklist | find /i "vfp9.exe"vfp9.exe 6808 Console 1 30.176 KBNoch eine: find /c /v "" zählt die Zeilen, die ankommen. Hinter ein dir /b gesetzt, zählt es, was in einem Ordner liegt:
dir /b C:\Windows | find /c /v ""102Keines der beiden Programme weiß, dass es das andere gibt. Jedes macht seinen Teil, und die Pipe verbindet sie. So arbeitet die Konsole: viele kleine Programme, die man kombiniert.
Der Exit-Code
Wenn ein Konsolenprogramm endet, gibt es dem, der es gestartet hat, eine Zahl zurück. Das ist der Exit-Code, und die Regel ist einfach: 0 heißt, es ist gut gelaufen, jede andere Zahl heißt, nicht. Was jede Zahl ungleich 0 bedeutet, entscheidet jedes Programm selbst.
In cmd steht der letzte Code in %ERRORLEVEL%:
ping -n 1 127.0.0.1 > nul
echo %ERRORLEVEL%Das sind die Codes der Befehle, die wir im Kurs benutzt haben:
| Befehl | Code |
|---|---|
ping -n 1 127.0.0.1 (antwortet) | 0 |
ping -n 1 -w 500 192.0.2.1 (niemand antwortet) | 1 |
git estado (Unterbefehl, den es nicht gibt) | 1 |
git log --onelin (falsch geschriebene Option) | 128 |
Mit dem Code entscheidet ein Skript, was es tut, ohne zu lesen, was das Programm geschrieben hat. && führt das Folgende nur aus, wenn der Code 0 war, und || nur, wenn nicht:
tasklist | find /i "vfp9.exe" > nul && echo VFP offen || echo VFP geschlossenfind gibt 0 zurück, wenn es den Text gefunden hat, und 1, wenn nicht. Also sagt diese Zeile, ob irgendein VFP läuft. Mit geöffnetem VFP antwortet sie „VFP offen“, geschlossen „VFP geschlossen“.
In PowerShell steht der Code in $LASTEXITCODE statt in %ERRORLEVEL%.
Der Exit-Code eines VFP-Programms
Es ist dieselbe Idee wie das RETURN einer Prozedur, nur zwischen Programmen: Das endende Programm hinterlässt dem startenden eine Zahl. Eine VFP-.exe, die mit QUIT endet, beendet sich immer mit 0, wie auch immer es gelaufen ist. QUIT nimmt keinen Code an. Für eine andere Zahl muss man Windows fragen:
DECLARE ExitProcess IN kernel32 INTEGER nCode
ExitProcess(3)Ich habe es ausprobiert, indem ich VFP mit einem Programm gestartet habe, das nur das tut: Es endet mit 3, und das daneben, das QUIT macht, mit 0. ExitProcess beendet den Prozess sofort, ohne das normale Herunterfahren von VFP. Rufen Sie es also erst auf, wenn Ihre Tabellen geschlossen und alles gespeichert ist.
Damit können eine .bat oder die Aufgabenplanung wissen, ob Ihr nächtlicher Lauf gut gegangen ist.
Umlaute, die verändert ankommen
Im ersten Teil kam beim Lesen der Ausgabe von ver aus VFP Versi¢n heraus. Das liegt daran, dass die Konsole, die RUN öffnet, mit der Codepage 850 aus MS-DOS schreibt, und VFP mit der 1252 von Windows arbeitet. chcp sagt Ihnen, welche die Konsole benutzt (bei mir auf Spanisch):
Página de códigos activa: 850Buchstaben mit Akzent oder Umlaut haben in beiden verschiedene Nummern. CPCONVERT überträgt den Text von einer Codepage in die andere:
RUN ver > version.txt
? CPCONVERT(850, 1252, FILETOSTR("version.txt"))Und jetzt steht da Microsoft Windows [Versión 10.0.26200.9457]. Ein deutsches Windows benutzt in der Konsole ebenfalls die 850; wenn chcp bei Ihnen eine andere Zahl meldet, setzen Sie diese ein.
Wenn Sie PowerShell benutzen
Die Umleitungen sind dieselben, mit zwei Unterschieden, die beim Lesen aus VFP Ärger machen:
>schreibt UTF-16. In der PowerShell 5.1, die mit Windows kommt, hinterlässtping -n 1 127.0.0.1 > ps.txteine Datei, die mit den BytesFF FEbeginnt und zwischen jedem Buchstaben ein Null-Byte hat: Sie ist doppelt so groß wie dieselbe Datei auscmd. Liest man sie mitFILETOSTRso, wie sie ist, kommt jeder Buchstabe mit einemCHR(0)dahinter.STRCONVmacht normalen Text daraus, wenn man vorher die ersten zwei Bytes weglässt:STRCONV(SUBSTR(FILETOSTR("ps.txt"), 3), 6).nulschreibt sich$null.git estado 2> nulschlägt in PowerShell fehl; was funktioniert, istgit estado 2> $null.
Zum Üben
In einem cmd, in Ihrem Testordner:
ping -n 1 127.0.0.1 > ausgabe.txt
ping -n 1 127.0.0.1 >> ausgabe.txt
type ausgabe.txt
git estado > ergebnis.txt
git estado 2> fehler.txt
type fehler.txt
dir /b C:\Windows | find /c /v ""
ping -n 1 -w 500 192.0.2.1 > nul && echo Antwortet || echo Keine AntwortUnd im Befehlsfenster von VFP:
RUN dir C:\Windows > ordner.txt
? CPCONVERT(850, 1252, FILETOSTR("ordner.txt"))In Teil 4: wie man die Hilfe eines Konsolenprogramms liest, und was in der Hilfe eines eigenen Programms stehen sollte.