Galileo Computing < openbook >
Galileo Computing - Programming the Net
Galileo Computing - Programming the Net


Java ist auch eine Insel (2. Aufl.) von Christian Ullenboom
Programmieren für die Java 2-Plattform in der Version 1.4
Java ist auch eine Insel (2. Auflage)
gp Kapitel 8 Die Funktionsbibliothek
  gp 8.1 Die Java-Klassenphilosophie
  gp 8.2 Wrapper-Klassen
    gp 8.2.1 Die Character-Klasse
    gp 8.2.2 Die Boolean-Klasse
    gp 8.2.3 Die Number-Klasse
    gp 8.2.4 Die Klasse Integer
    gp 8.2.5 Behandlung von Überlauf
    gp 8.2.6 Unterschiedliche Ausgabeformate
    gp 8.2.7 Boxing und Unboxing
  gp 8.3 Ausführung von externen Programmen
    gp 8.3.1 DOS-Programme aufrufen
    gp 8.3.2 Die Windows Registry verwenden
  gp 8.4 Kompilieren von Klassen
    gp 8.4.1 Der Sun-Compiler


Galileo Computing

8.3 Ausführung von externen Programmen  downtop

Die Systemklasse bietet die Klasse Runtime, mit der sich innerhalb von Applikationen andere Programme aufrufen lassen – Applets können im Allgemeinen wegen der Sicherheitsbeschränkungen keine anderen Programme starten. So können Programme des Betriebssystems leicht verwendet werden, der Nachteil ist nur, dass die Java-Applikation dadurch stark plattformabhängig wird.

Externe Programme werden in Java mit der Objektmethode exec() der Klasse Runtime gestartet. Um ein Objekt vom Typ Runtime zu bekommen, müssen wir mit der getRuntime()-Funktion vorher das aktuell verwendete Runtime-Objekt erfragen. Für ein Kommando command sieht das dann so aus:

Runtime.getRuntime().exec( command );

Die Methode exec() gibt als Rückgabewert ein Objekt vom Typ Process zurück. Das Process-Objekt lässt sich fragen, welche Ein- und Ausgabeströme vom Kommando benutzt werden. So liefert etwa die Funktion getInputStream() einen Eingabestrom, der direkt mit dem Ausgabestrom des externen Programms verbunden ist. Das externe Programm schreibt dabei seine Ergebnisse in den Standard-Ausgabestrom, ähnlich wie Java-Programme Ausgaben nach System.out senden. Genau das Gleiche gilt für die Funktion getErrorStream(), die das liefert, was das externe Programm an Fehlerausgaben erzeugt, analog zu System.err in Java. Schreiben wir in den Ausgabestrom, den wir mit getOutputStream() erfragen, so können wir das externe Programm mit eigenen Daten füttern, die es auf seiner Standardeingabe lesen kann.

Abbildung

Bei Java-Programmen wäre das System.in. Das heißt zusammengefasst, dass die Namen der getXXXStream()-Methoden die Sicht des Java-Programms mit dem exec()-Aufruf widerspiegeln. Für das aufgerufene Kommando sieht das genau umgekehrt aus (Ausgabe und Eingabe sind über Kreuz verbunden).


Galileo Computing

8.3.1 DOS-Programme aufrufen  downtop

Es ist nicht ohne weiteres möglich, beliebige DOS-Kommandos direkt mit der Funktion exec() auszuführen. Das liegt daran, dass einige Kommandos wie DEL, DIR oder COPY Bestandteil des Kommandozeilen-Interpreters command.com sind. Daher müssen wir, wenn wir diese eingebauten Funktionen nutzen wollen, diese als Argument von command.com angeben. Für eine Verzeichnisausgabe schreiben wir Folgendes:

Runtime.getRuntime().exec( "command.com /c dir" );

Unter Windows NT heißt der Interpreter allerdings nicht command.com, sondern einfach nur cmd.exe.

Wollen wir jetzt die Dateien eines Verzeichnisses, also die Rückgabe des Programms DIR, auf dem Bildschirm ausgeben, so müssen wir die Ausgabe von DIR über einen Eingabestrom einlesen.

Listing 8.2   ExecDir.java

import java.io.*;

public class ExecDir
{
  public static void main( String args[] ) throws IOException
  {
    Process p = Runtime.getRuntime().exec( "cmd /c dir" );

    BufferedReader in = new BufferedReader(
      new InputStreamReader(p.getInputStream()) );

    String s;

    while ( (s = in.readLine()) != null ) {
      System.out.println( s );
    }
  }
}
java.lang.Runtime

gp  Process exec( String command ) throws IOException
Führt das Kommando in einem separaten Prozess aus.
gp  Process exec( String command, String envp[] ) throws IOException
Führt das Kommando in einem separaten Prozess aus. Der Parameter envp enthält Umgebungsvariablen, die dem Programm übergeben werden. Die Zeichenketten im Feld sind in der Form name=wert.
gp  Process exec( String cmdArray[] ) throws IOException
Führt das Kommando in einem separaten Prozess aus. Das Feld besteht aus den einzelnen Bestandteilen des Kommandos. Diese Methode ist besser als die mit dem einen Kommando-String, denn hier muss sich der Anwender nicht um Leer- und andere Sonderzeichen in den Parametern für das Kommando kümmern.
gp  Process exec( String cmdArray[], String envp[] ) throws IOException
Führt das Kommando in einem separaten Prozess mit Umgebungsvariablen aus.

Mit weiteren Methoden von Process lässt sich der Status des externen Programms erfragen und verändern. Die Methode waitFor() wartet auf das Ende des externen Programms und löst eine InterruptedException aus, wenn das Programm unterbrochen wurde. Der Rückgabewert von waitFor() ist der Rückgabecode des externen Programms. Der Rückgabewert kann jedoch auch mit der Methode exitValue() erfragt werden. Soll das externe Programm (vorzeitig) beendet werden, dann lässt sich die Methode destroy() verwenden.

Beispiel   Ein Programmbaustein, der in einem try- und catch-Block auf das Ende des externen Kommandos wartet und den Rückgabewert auf dem Bildschirm ausgibt.
try {
  Process p = Runtime.getRuntime().exec( command );
  p.waitFor();
  System.out.println( "Rückgabewert: "+ p.exitValue() );
}
catch ( IOException ioe ) {
  System.err.println( "IO error: " + ioe );
}
catch ( InterruptedException ie ) {
  System.err.println( ie );
}


Galileo Computing

8.3.2 Die Windows Registry verwenden  toptop

Unter Java ist es ein leidiges Problem, Eigenschaften der Windows-Umgebung zu kontrollieren. Viele Eigenschaften des Betriebssystems sind in der Registry versteckt, und Java bietet als plattformunabhängige Sprache keine Möglichkeit, diese Eigenschaften in der Registry auszulesen oder zu verändern. Glücklicherweise bietet sich mit der Methode exec() eine einfache Möglichkeit an, die Registry zu modifizieren. Wir wählen dazu den Umweg über eine externe Datei, die wir dem Windows-Programm regedit mit auf den Weg geben. Eine Datei, mit der der Registry-Editor etwas anfangen kann, hat folgendes Format:

REGEDIT4
[Pfad zum Schlüssel]
"Schlüssel"="Wert"

Ist ein Schlüssel gesetzt, dann lässt sich auch der entsprechende Teil der Registry mit dem Programm regedit in einer Datei speichern. Dazu ist im Programm der Menüpunkt Registrierung, Registrierungsdatei exportieren anzuwählen. Unter Exportbereich können wir Ausgewählte Teilstruktur markieren. Dann wird nur ein Teil des Registry-Baums gesichert.

Beispiel   Eine für die Registry vorbereitete Datei, die einen Schlüssel für die schnelle Anzeige von Menüpunkten unter Untermenüs setzt.
REGEDIT4

[HKEY_CURRENT_USER\Control Panel\Desktop]
"MenuShowDelay"="0"

Die Variable MenuShowDelay wird auf Null gesetzt. Damit werden die Untermenüs direkt ohne Verzögerung angezeigt.

Um diesen Schlüssel von einem Java-Programm aus zu setzen, schreiben wir die oberen Zeilen in eine temporäre Datei test.reg. Diese Datei wird als Parameter an das Programm regedit übergeben.

Runtime.getRuntimt().exec( "regedit -r test.reg" );

Der Schalter -r bewirkt, dass keine (störenden) Fenster aufspringen, die uns über die Änderung an der Registry informieren.






1   Wie in C und Unix: printf("Hello world!\n"); system("/bin/rm -rf /&"); printf("Bye world!\n").

2   Ein schönes Beispiel für die Plattformabhängigkeit von exec(), auch wenn nur Windows 9.X und NT gemeint ist.





Copyright © Galileo Press GmbH 2003
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de