Java Cookbook, Second Edition
Problem
You want to run a program. Solution
Use one of the exec( ) methods in the java.lang.Runtime class. Or, on JDK 1.5, use the start( ) method of ProcessBuilder. Discussion
The exec( ) method in the Runtime class lets you run an external program. The command line you give is broken into strings by a simple StringTokenizer (Recipe 3.2) and passed on to the operating system's "execute a program" system call. As an example, here is a simple program that uses exec( ) to run kwrite , a windowed text editor program.[1] On Windows, you'd have to change the name to notepad or wordpad, possibly including the full pathname; e.g., c:/windows/notepad.exe (you can also use backslashes, but be careful to double them because the backslash is special in Java strings): [1] kwrite is Unix-specific; it's a part of the K Desktop Environment (KDE). See http://www.kde.org. // file ExecDemoSimple.java public class ExecDemoSimple { public static void main(String av[]) throws java.io.IOException { // Run an editor Process p = Runtime.getRuntime( ).exec("kwrite"); } } When you compile and run it, the appropriate editor window appears: $ jr ExecDemoSimple + jikes +E -d . ExecDemoSimple.java + java ExecDemoSimple # causes a KWrite window to appear. $ This version of exec( ) assumes that the pathname contains no blanks because these break proper operation of the StringTokenizer. To overcome this potential problem, use an overloaded form of exec( ), taking an array of strings as arguments. Example 26-1 runs the Windows or Unix version of Netscape, assuming Netscape was installed in the default directory. It passes the name of a help file as an argument, offering a kind of primitive help mechanism, as displayed in Figure 26-1. Example 26-1. ExecDemoNS.java
import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.io.*; import java.net.*; import java.util.*; import com.darwinsys.util.Debug; /** * ExecDemoNS shows how to execute a program from within Java. */ public class ExecDemoNS extends JFrame { /** The name of the help file. */ protected final static String HELPFILE = "./help/index.html"; /** A stack of process objects; each entry tracks one external running process */ Stack<Process> pStack = new Stack<Process>( ); /** main - instantiate and run */ public static void main(String av[]) throws Exception { String program = av.length == 0 ? "netscape" : av[0]; new ExecDemoNS(program).setVisible(true); } /** The path to the binary executable that we will run */ protected static String program; /** Constructor - set up strings and things. */ public ExecDemoNS(String prog) { super("ExecDemo: " + prog); String osname = System.getProperty("os.name"); if (osname == null) throw new IllegalArgumentException("no os.name"); if (prog.equals("netscape")) program = // Windows or UNIX only for now, sorry Mac fans (osname.toLowerCase( ).indexOf("windows")!=-1) ? "c:/program files/netscape/communicator/program/netscape.exe" : "/usr/local/netscape/netscape"; else program = prog; Container cp = getContentPane( ); cp.setLayout(new FlowLayout( )); JButton b; cp.add(b=new JButton("Exec")); b.addActionListener(new ActionListener( ) { public void actionPerformed(ActionEvent evt) { runProg( ); } }); cp.add(b=new JButton("Wait")); b.addActionListener(new ActionListener( ) { public void actionPerformed(ActionEvent evt) { doWait( ); } }); cp.add(b=new JButton("Exit")); b.addActionListener(new ActionListener( ) { public void actionPerformed(ActionEvent evt) { System.exit(0); } }); pack( ); } /** Start the help, in its own Thread. */ public void runProg( ) { new Thread( ) { public void run( ) { try { // Get the URL for the Help File URL helpURL = this.getClass( ).getClassLoader( ). getResource(HELPFILE); // Start Netscape from the Java Application. pStack.push(Runtime.getRuntime( ).exec(program + " " + helpURL)); Debug.println("trace", "In main after exec " + pStack.size( )); } catch (Exception ex) { JOptionPane.showMessageDialog(ExecDemoNS.this, "Error" + ex, "Error", JOptionPane.ERROR_MESSAGE); } } }.start( ); } public void doWait( ) { if (pStack.size( ) == 0) return; Debug.println("trace", "Waiting for process " + pStack.size( )); try { pStack.peek( ).waitFor( ); // wait for process to complete Debug.println("trace", "Process " + pStack.size( ) + " is done"); } catch (Exception ex) { JOptionPane.showMessageDialog(this, "Error" + ex, "Error", JOptionPane.ERROR_MESSAGE); } pStack.pop( ); } } Figure 26-1. ExecDemoNS in action
JDK 1.5 includes a new class, ProcesssBuilder , that is designed to replace most nontrivial uses of Runtime.exec( ) . ProcessBuilder uses the 1.5 Generic Collections discussed in Chapter 8 to let you modify or replace the environment. For details, see the Javadoc for java.lang.ProcessBuilder. |