GWBASIC.EXE als auch QuickBASIC bieten mit dem
SHELL
-Kommando die Möglichkeit an, Programme ausserhalb von
BASIC direkt auf DOS/Windowsebene laufen zu lassen. Dabei funktioniert dies
auch mit 32-Bit-Applikationen sogar bestens, also beispielsweise mit
10 ' Internet Explorer 5.01 aus GWBASIC.EXE heraus! 20 SHELL "C:\PROGRA~1\INTERN~1\IEXPLORE http://www.hofen.ch/~andreas/"
einen Webbrowser zu starten. Siehe auch BASIC in modernen Betriebssystemumgebungen.
Anmerkung für Amiga-Benutzer: Dort gibt es leider :-( keinen SHELL
-Befehl, so dass Sie auf
CALL Exec&()
der dos.library ausweichen
müssen.
Achtung: Denken Sie immer daran, dass GWBASIC.EXE und QuickBASIC für DOS reine Real Mode-Programme sind, welche also im Intel 8088/8086-Modus wie bei einem uralten IBM PC/XT laufen! Aus diesem Grund unterliegt die Speicherverwaltung voll der bekannten 640 KB-Limite, selbst wenn Ihr PC mit 256 MB Arbeitsspeicher bestückt ist.
Mit folgenden Schritten können Sie den Verbrauch recht eindrücklich messen:
C:\BASICPRG>mem
Speichertyp Insgesamt = Verwendet + Frei
----------------- ---------- --------- ---------
Konventioneller 640K 27K 613K
Hoher 123K 72K 51K
Reserviert 128K 128K 0K
Erweiterung (XMS) 9'349K 2'407K 6'942K
----------------- ---------- --------- ---------
Insg. Speicher 10'240K 2'634K 7'606K
Insg. unter 1 MB 763K 98K 664K
Maximale Größe für ausführbares Programm 613K (628'000 Byte)
Größter freier Block im hohen Speicherblock 51K (51'952 Byte)
MS-DOS ist resident im oberen Speicherbereich (High Memory Area).
C:\BASICPRG>gwbasic
GW-BASIC 3.23
(C) Copyright Microsoft 1983,1984,1985,1986,1987,1988
60300 Byte frei
Ok
shell
Microsoft(R) Windows 98
(C)Copyright Microsoft Corp 1981-1998.
C:\BASICPRG>mem
Speichertyp Insgesamt = Verwendet + Frei
----------------- ---------- --------- ---------
Konventioneller 640K 108K 532K
Hoher 123K 72K 51K
Reserviert 128K 128K 0K
Erweiterung (XMS) 9'349K 2'407K 6'942K
----------------- ---------- --------- ---------
Insg. Speicher 10'240K 2'715K 7'525K
Insg. unter 1 MB 763K 180K 583K
Maximale Größe für ausführbares Programm 532K (544'560 Byte)
Größter freier Block im hohen Speicherblock 51K (51'952 Byte)
MS-DOS ist resident im oberen Speicherbereich (High Memory Area).
C:\BASICPRG>exit
Ok
print 628000 - 544560
83440 <= Rund 81½ KB werden von GWBASIC.EXE belegt!
Ok
system
C:\BASICPRG>_
Bei QBASIC.EXE ist es erheblich mehr: Rund 367¼ KB dieser wertvollen 640 KB konventionellen Speicher gehen weg! Aus diesem Grund macht es in einem solchen Fall Sinn, auch unter Windows 95 und 98 die beiden Dateien CONFIG.SYS und AUTOEXEC.BAT wie in den guten, alten MS-DOS 6.22/Windows 3.1x-Zeiten zu optimieren. Ob das gute, alte MEMMAKER.EXE unter Windows 95 und 98 auch noch eingesetzt werden kann, ist mir unbekannt, manuelle Änderungen wie beispielsweise
DEVICE=C:\WINDOWS\HIMEM.SYS /VERBOSE DEVICE=C:\WINDOWS\EMM386.EXE NOEMS HIGHSCAN VERBOSE
am Anfang der Datei C:\CONFIG.SYS einfügen sowie alle Gerätetreiber mit LH laden und innerhalb der AUTOEXEC.BAT vor jedem TSR ein LOADHIGH oder LH voranstellen sollten Sie in jedem Fall versuchen.
Diese Frage erhielt ich schon einige Male per e-Mail zugestellt. Daher ganz kurz und bündig:
In beiden Fällen wird Ihr Programm beendet.
Während Sie bei END
noch in der BASIC-Entwicklungsumgebung
bleiben, wird mit SYSTEM
BASIC vollständig
verlassen.
GWBASIC.EXE-Programmierer sollten dabei beachten, ihr Programm vorher mit save gespeichert zu haben, da keine Sicherheitsabfrage stattfindet!
Hinweis: Bei als .EXE-Datei übersetzten Programmen entfällt dieser Unterschied, da Sie nach Programmende sowieso wieder ins DOS zurückkommen.
Im folgenden zeige ich Ihnen, wie Sie ein BASIC-Programm in eine .BAT-Datei integrieren können. Eine nützliche Anwendung davon ist das Aufrufen eines BASIC-Programms innerhalb der AUTOEXEC.BAT beim Systemstart, beispielsweise ein Startmenü.
Erstellen Sie mit EDIT.COM eine Datei MEINBAT.BAT mit folgendem Inhalt:
@ECHO OFF REM Dies ist eine COMMAND.COM-Stapelverarbeitungsdatei für MS-DOS ECHO Jetzt geht's dann gleich ins BASIC hinein GWBASIC MEINPROG ECHO BASIC-Programm fertig, wieder MS-DOS
Erstellen Sie noch in GWBASIC.EXE folgende kleine Programm MEINPROG.BAS
10 ' Wir sind in BASIC 20 PRINT "Jetzt läuft gerade mein BASIC-Programm" 30 SYSTEM
So, und nun können Sie das Ganze mit
C:\BASICPRG>meinbat
einmal laufen lassen.
Diese Variante betrifft nur die Interpreter-Version QBASIC.EXE.
@ECHO OFF REM Dies ist eine COMMAND.COM-Stapelverarbeitungsdatei für MS-DOS ECHO Jetzt geht's dann gleich ins BASIC hinein QBASIC /RUN MEINPROG ECHO BASIC-Programm fertig, wieder MS-DOS
' Wir sind in BASIC PRINT "Jetzt läuft gerade mein BASIC-Programm" SYSTEM
Beim BASIC-Compiler entfallen bekanntlich all diese Umwege.
Sowohl MS-DOS als auch Windows verwenden zahlreiche Umgebungsvariablen:
C:\WINDOWS>set TMP=C:\WINDOWS\TEMP TEMP=C:\WINDOWS\TEMP winbootdir=C:\WINDOWS COMSPEC=C:\WINDOWS\COMMAND.COM PATH=C:\WINDOWS;C:\WINDOWS\COMMAND;E:\DOS\EXTRAS;E:\DOS PROMPT=$p$g windir=C:\WINDOWS BLASTER=A220 I5 D1 H5 P330 T6 E620 CMDLINE=gwbasic C:\WINDOWS>_
Sowohl GWBASIC.EXE als auch QuickBASIC bieten mit der
ENVIRON$()
-Funktion einen sauberen Weg an, um auf diese
Informationen zugreifen zu können als auch Werte zu setzen.
Eine sehr sinnvolle Anwendung davon ist die Verwendung des TEMP-Verzeichnisses von Windows. Damit Ihr BASIC-Programm auf jedem PC voll lauffähig wird, sollten Sie so etwas tunlichst vermeiden:
10 ' So besser nicht! 20 INPUT "Dateipfad und Gruppe, z.B. C:\DATEN\*.XLS"; PF$ 30 SHELL "dir " + PF$ + " /b >C:\TMP\~TEMPDAT.TMP" 40 OPEN "C:\TMP\~TEMPDAT.TMP" FOR INPUT AS 1 50 WHILE NOT EOF(1) 60 LINE INPUT#1, D$ 70 ' Datei D$ verarbeiten 80 WEND 90 CLOSE 1: KILL "C:\TMP\~TEMPDAT.TMP" 100 END
Der fatale Fehler: Es wird das Vorhandensein eines Laufwerkes C:\ vorausgesetzt mit einem Verzeichnis C:\TMP, was häufig nicht möglich und sinnvoll ist:
Aus all diesen Gründen sollten Sie dieser Variante den Vorzug geben:
10 ' So ist es korrekt! 20 RANDOMIZE TIMER 30 INPUT "Dateipfad und Gruppe, z.B. C:\DATEN\*.XLS"; pf$ 40 TP$ = ENVIRON$("TEMP") 50 IF TP$<>"" THEN 110 60 PRINT "Die TEMP-Variable ist nicht gesetzt. Stellen Sie sicher, dass sich" 70 PRINT "in der Datei AUTOEXEC.BAT eine Zeile" 80 PRINT "SET TEMP=C:\TEMP" 90 PRINT "oder etwas ähnliches befindet." 100 SYSTEM 110 IF RIGHT$(TP$, 1) <> "\" THEN TP$ = TP$ + "\" 120 ' Möglichst einen eindeutigen Namen wählen, um Konflikte 130 ' zu vermeiden, wenn unter Windows (Multitasking!) dieses Programm 140 ' gleichzeitig mehrere Male aufgerufen wird 150 TP$ = TP$ + "~" 160 FOR I%=1 TO 3: TP$ = TP$ + CHR$(65 + CINT(INT(26! * RND))): NEXT I% 170 TP$ = TP$ + MID$(TIME$, 4, 2) + RIGHT$(TIME$, 2) + ".TMP" 180 SHELL "dir " + PF$ + " /b >" + TP$ 190 OPEN TP$ FOR INPUT AS 1 200 WHILE NOT EOF(1) 210 LINE INPUT#1, D$ 220 ' Datei D$ verarbeiten 230 WEND 240 CLOSE 1: KILL TP$ 250 END
Anmerkung für UNIX- und Linux-Benützer: Bisher ist mir noch kein
Weg bekannt, um eine eindeutige Prozessidentifikation wie
$$
der Korn-Shell bestimmen zu können, aus diesem Grund wird
mit Hilfe der Uhrzeit sowie des Zufallsgenerators versucht einen
möglichst einmaligen Dateinamen zu erzeugen. Die Zeilen 150 bis 170 bilden
also einen Ersatz für die in jedem UNIX- und Linux-Betriebssystem
vorhandene tmpnam()
-Funktion.
Beim Setzen von Umgebungsvariablen gilt bei DOS und Windows dieselbe Philosophie wie bei jedem UNIX und Linux:
Nur bei den Sohnprozessen kann die Umgebung gesetzt werden, nicht vom Vater. Dies sollte man speziell bei Programmen für die AUTOEXEC.BAT beachten!
Beispielszenario:
C:\BASICPRG>echo x%VAR1%x xx C:\BASICPRG>set VAR1=Andreas C:\BASICPRG>echo x%VAR1%x xAndreasx C:\BASICPRG>gwbasic GW-BASIC 3.23 (C) Copyright Microsoft 1983,1984,1985,1986,1987,1988 60300 Byte frei Ok print ">";environ$("VAR1");"< >";environ$("VAR2");"<" >Andreas< >< Ok environ "VAR2=Meile" Ok print ">";environ$("VAR2");"<" >Meile< OK shell Microsoft(R) Windows 98 (C)Copyright Microsoft Corp 1981-1998. C:\BASICPRG>echo x%VAR1%x%VAR2%x%VAR3%x xAndreasxMeilexx C:\BASICPRG>set VAR3=Hofen C:\BASICPRG>echo x%VAR3%x xHofenx C:\BASICPRG>exit <= Sohnprozess endet Ok print ">";environ$("VAR1");"< >";environ$("VAR2");"< >";environ$("VAR3");"<" >Andreas< >Meile< >< <= VAR3 existiert nicht mehr! Ok system <= Sohnprozess endet C:\BASICPRG>echo x%VAR1%x%VAR2%x%VAR3%x xAndreasxxx <= VAR2 existiert auch nicht mehr! C:\BASICPRG>_
Erklärung: Exakt wie bei jedem UNIX und Linux üblich erstellt der exec-Systemaufruf von MS-DOS für den sog. Sohnprozess (engl. child process) eine vollständige Kopie von der Umgebungsvariablentabelle. Daher geht beim Beenden der Sohnprozesse mit exit bzw. system diese Kopie mit allen Änderungen jeweils verloren.