Externe Programme aus Java heraus aufrufen

Sollen externe Programme von Java heraus aufgerufen werden, wird der von Java propagierte Ansatz der Plattformunabhängigkeit verlassen. Trotzdem kann man sich natürlich vorstellen, dass man genau zu einer spezifische Plattform z.B. administrative Auswertungen zusammentragen oder externe Programme wie einen Mail-Client durch Implementierung einer systemspezifischen Weiche aufrufen möchte.

Sicherheitshalber sollte beim Einsatz externer Programmaufrufe zunächst einmal geprüft werden, ob die derzeitige Systemumgebung auch derjenigen entspricht, die man erwartet. Das folgende Beispiel zeigt einerseits, wie man diese Abfrage implementieren kann und wird darüber hinaus andererseits als Rahmen für die weiter unten aufgeführten Beispiele genutzt:

import java.io.*;

public class ProcExecExamples 
{ public static void main(String[] args)  throws Exception
  { if (isWindowsSystem())
    { System.out.println("Windows System");
      // exec windows commands ...
    }
    else if (isLinuxSystem())
    { System.out.println("Linux System");
      // exec linux commands ...
    }
    else
    { System.err.println("Unknown System");
      System.exit(1);
    }
  }

  static boolean isWindowsSystem()
  { String osName = System.getProperty("os.name").toLowerCase();
    return osName.indexOf("windows") >= 0;
  }
  
  static boolean isLinuxSystem()
  { String osName = System.getProperty("os.name").toLowerCase();
    return osName.indexOf("linux") >= 0;
  }
}

Generell werden externe Programme aus Java heraus mit dem Befehl:
Runtime.getRuntime().exec(command);
aufgerufen. Während allerdings unter Linux/Unix direkt das Programm ausgeführt wird, ist unter Windows der Kommando-Interpreter zu starten, dem der eigentliche Befehl als Parameter mitgegeben wird:
Runtime.getRuntime().exec("cmd /c " + command);

Soll die Ausgabe eines dieser System Kommandos ausgewertet werden, kann man diese über den InputStream des aktuellen Process-Objektes einfangen:

...
    if (isWindowsSystem())
    { System.out.println("Windows System");
      printWindowsCommand("dir C:\\Users\\hermann\\temp");
    }
...
  static void printWindowsCommand(String command) throws Exception
  { System.out.println("Windows command: " + command);
    String line;
    Process process = Runtime.getRuntime().exec("cmd /c " + command);
    Reader r = new InputStreamReader(process.getInputStream());
    BufferedReader in = new BufferedReader(r);
    while((line = in.readLine()) != null) System.out.println(line);
    in.close();
  }
Windows System
Windows command: dir C:\Users\hermann\temp
 Volume in Laufwerk C: hat keine Bezeichnung.
 Volumeseriennummer: DEBB-3C05

 Verzeichnis von C:\Users\hermann\temp

04.03.2008  16:47    <DIR>          .
04.03.2008  16:47    <DIR>          ..
09.02.2008  11:35               856 FilesExample1.java
09.02.2008  11:05               942 FilesExample2.java
04.03.2008  16:09             1.586 ProcExecExamples.java
               3 Datei(en),          3.384 Bytes
               2 Verzeichnis(se), 107.189.878.784 Bytes frei
...
    else if (isLinuxSystem())
    { System.out.println("Linux System");
      printLinuxCommand("ps -U hermann u");
    }
...
  static void printLinuxCommand(String command) throws Exception
  { System.out.println("Linux command: " + command);
    String line;
    Process process = Runtime.getRuntime().exec(command);
    Reader r = new InputStreamReader(process.getInputStream());
    BufferedReader in = new BufferedReader(r);
    while((line = in.readLine()) != null) System.out.println(line);
    in.close();
  }
Linux System
Linux command: ps -U hermann u
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
hermann   2811  0.0  0.7   9040  1844 ?        S    13:17   0:00 sshd: hermann@pts/0
hermann   2812  0.0  0.8   4720  2292 pts/0    Ss+  13:17   0:00 -bash
hermann   2867  0.0  0.7   4452  1996 tty1     Ss+  14:59   0:00 -bash
hermann   3671  0.0  0.7   9040  1844 ?        S    15:31   0:00 sshd: hermann@pts/1
hermann   3672  0.1  0.8   4720  2284 pts/1    Ss   15:31   0:00 -bash
hermann   3703 32.0  5.3 232720 13804 pts/1    Sl+  15:34   0:00 /usr/lib/jvm/java-1.5.0
-sun-1.5.0_update17/jre/bin/java ProcExecExamples
hermann   3714  0.0  0.3   2504   960 pts/1    R+   15:34   0:00 /bin/ps -U hermann u

Wenn es nicht um die Ausgabe des System-Kommandos geht, sondern wenn ganz einfach nur ein externes Programm gestartet werden soll, reicht es natürlich, wenn
Runtime.getRuntime().exec(command); unter Linux, bzw.
Runtime.getRuntime().exec("cmd /c " + command); unter Windows
aufgerufen wird.

Zudem besteht die Möglichkeit, das zum Mime-Type einer URL gehörende Standardprogramm aufzurufen, indem man den Kommando-Interpreter unter Windows mit einer zusätzlichen start- und unter Linux mit einer zusätzlichen xdg-open-Anweisung versieht:

...
    execProgram("http://www.google.de");
    execProgram("mailto:hew@wsoftware.de");
    execProgram("myDocument.pdf");
...
  static void execProgram(String command) throws Exception
  { if (isWindowsSystem())
    { Runtime.getRuntime().exec("cmd /c start " + command);
    }
    if (isLinuxSystem())
    { Runtime.getRuntime().exec("xdg-open " + command);
    }
  }