Solved

Running Command Prompt within Java GUI

Posted on 2003-10-23
10
1,638 Views
Last Modified: 2013-11-23
How do I run the Command prompt within a java GUI?(i.e. I know how to "invoke" the Dos Prompt from java, what I need is to run Dos and its commands within the GUI).

Below is the code I've been working with, it only display the first lines of the command prompt on the text field and doesn't allow me to interact with dos. What do I need to do?
Please I do need a clear answer.
THANKS ever so much experts.

import java.lang.*;
import java.io.*;
import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.*;

public class Dos implements Runnable
{
     private PipedOutputStream pipeout;
     private PipedOutputStream pipeerr;
     String command = "cmd";

     public Dos ( String[] cmd )
     
     {
      pipeout = null;
      pipeerr = null;
     }

     public void run ()
     {
      exec ();
     }

     public void exec ()
     {

          // Class to redirect the process input stream to a piped output stream

          class OutputMonitor implements Runnable
          {
               InputStream is;
               PipedOutputStream pout;

               public OutputMonitor ( InputStream i, PipedOutputStream p )
               {
                is = i;
                pout = p;
               }
               public void run ()
               {
                    try
                    {
                         int inputChar;

                         for ( ;; )
                         {
                            inputChar = is.read();
                            if ( inputChar == -1 )
                            { break; }

                            if ( pout == null )
                            {
                                 System.out.write ( inputChar );
                            }
                            else
                            {
                                 pout.write ( inputChar );

                            }
                       }
                       if ( pout != null )
                       {
                            pout.flush ();
                            pout.close ();
                       }
                       else
                       {
                            System.out.flush();
                       }
                    }
                    catch ( Exception e ) { e.printStackTrace (); }
               }
            }

          try
          {
               Runtime r = Runtime.getRuntime ();
               Process p = r.exec (command);

               OutputMonitor out = new OutputMonitor ( p.getInputStream (), pipeout );
               OutputMonitor err = new OutputMonitor ( p.getErrorStream (), pipeerr );

               Thread t1 = new Thread ( out  );
               Thread t2 = new Thread ( err );

               t1.start ();
               t2.start ();

          }
          catch ( Exception e ) { e.printStackTrace (); }

     }

     public PipedInputStream getInputStream () throws IOException
     {
          pipeout = new PipedOutputStream ();
          return new PipedInputStream ( pipeout );
     }

     public PipedInputStream getErrorStream () throws IOException
     {
          pipeerr = new PipedOutputStream ();
          return new PipedInputStream ( pipeerr );
     }

     public void execInThread ()
     {
          Thread t = new Thread ( this );
          t.start ();
     }

     public static JPanel getContentPane ( JTextArea ta )
     {

          JPanel p = new JPanel ( new BorderLayout () );
          JPanel bottom = new JPanel ( new FlowLayout () );
          JButton button = new JButton ( " Exit " );
          button.addActionListener ( new ActionListener ( )
                              {
                                   public void actionPerformed ( ActionEvent e )
                                   {
                                        System.exit ( 0 );
                                   }
                              }
                         );


          bottom.add ( button );

          p.add ( new JScrollPane ( ta ), BorderLayout.CENTER );
          p.add ( bottom, BorderLayout.SOUTH );
          p.setPreferredSize ( new Dimension ( 640,480 ) );
          return p;
    }

     public static void main ( String[] arg )
     {
         
          // Class run in a thread,listens for the process output
          // and forwards it to the UI via invokeLater()

          class GuiUpdate implements Runnable
          {
               private PipedInputStream pin;
               private PipedInputStream perr;
               private JTextArea outputArea;

               GuiUpdate ( JTextArea textArea, PipedInputStream in )
               {
                 pin = in;
                 outputArea = textArea;
               }

              public void run ()
               {
                    // Class to run on the event dispatch thread to update the GUI

                    class UpdateSwing implements Runnable
                    {
                         String update;
                         JTextArea swingTextArea;

                         public UpdateSwing ( JTextArea a, String s )
                         {
                              update = s;
                              swingTextArea = a;
                         }
                         public void run ()
                         {
                              outputArea.append ( update + "\n" );
                         }
                    }

                    try
                    {
                         // Read file before displaying
                         BufferedReader r = new BufferedReader ( new InputStreamReader ( pin ) );
                         String line;

                         for ( ;; )
                         {
                              line = r.readLine ();
                              if ( line == null ) { break; }

                              SwingUtilities.invokeLater ( new UpdateSwing ( outputArea, line ) );

                              Thread.yield ();
                         }
                    }
                    catch ( Exception e ) { e.printStackTrace (); }
               }
          }

          // Create and invoke GUI

          JFrame f = new JFrame ( "GUI for Dos" );
          f.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
          JTextArea textOutput = new JTextArea ();
          f.getContentPane().add ( getContentPane ( textOutput ) );
          f.pack();
          f.show ();

          // Start command and capture output in the scrollable text area

          try
          {
               // Create command and setup the pipes

               Dos d = new Dos ( arg );

               PipedInputStream stdout_pipe = d.getInputStream ();
               PipedInputStream stderr_pipe = d.getErrorStream ();
               d.execInThread ( );
               
              // Results

               Thread t1 = new Thread ( new GuiUpdate ( textOutput, stdout_pipe ) );
               Thread t2 = new Thread ( new GuiUpdate ( textOutput, stderr_pipe ) );

               t1.start ();
               t2.start ();

          }
          catch ( Exception e ) { e.printStackTrace (); }
     }
}

0
Comment
Question by:eric2405
  • 7
  • 2
10 Comments
 
LVL 3

Expert Comment

by:savalou
ID: 9606596
A few comments:

1.  I don't think you should be closing everything down if there is no input in the run() method of OutputMonitor.
2.  Any new commands to be run should be writen to the OutputStream of your Process.
3.  You could set a KeyListener on your TextArea to listen for key presses, and echo these to the OutputStream of your Process.

class MyKeyListener implements KeyListener {

      public void keyTyped(KeyEvent e) {
        System.out.println("key typed: " + e.getKeyChar());
      }
      public void keyPressed(KeyEvent e) {
        System.out.println("pressed");
      }
      public void keyReleased(KeyEvent e) {
        System.out.println("released");
      }
}

I think you should move some of the code around and break it up into different classes for clarity (you probably had them all in one file to post here?).

Good luck.
0
 
LVL 9

Accepted Solution

by:
doronb earned 500 total points
ID: 9608031
I have the whole code for you broken into classes...

//___________________________________________________________________
/* FILE: dev/exec/util/ExecProcessor.java */
//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
package dev.exec.util;

public interface ExecProcessor {
      // This method gets called when the process sent us a new input String..
      public void processNewInput(String input);

      // This method gets called when the process sent us a new error String..
      public void processNewError(String error);

      // This method gets called when the process has ended..
      public void processEnded(int exitValue);
}
//___________________________________________________________________
/* FILE: dev/exec/util/ExecHelper.java */
//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
package dev.exec.util;

import java.io.*;

public class ExecHelper implements Runnable {
      // Allocate 1K buffers for Input and Error Streams..
      private byte[] inBuffer = new byte[1024];
      private byte[] errBuffer = new byte[1024];
      // Declare internal variables we will need..
      private Process process;
      private InputStream pErrorStream;
      private InputStream pInputStream;
      private OutputStream pOutputStream;
      private PrintWriter outputWriter;
      private Thread processThread;
      private Thread inReadThread;
      private Thread errReadThread;
      private ExecProcessor handler;
      // Private constructor so that no one can create a new ExecHelper directly..
      private ExecHelper(ExecProcessor ep, Process p) {
            // Save variables..
            handler = ep;
            process = p;
            // Get the streams..
            pErrorStream = process.getErrorStream();
            pInputStream = process.getInputStream();
            pOutputStream = process.getOutputStream();
            // Create a PrintWriter on top of the output stream..
            outputWriter = new PrintWriter(pOutputStream, true);
            // Create the threads and start them..
            processThread = new Thread(this);
            inReadThread = new Thread(this);
            errReadThread = new Thread(this);
            // Start Threads..
            processThread.start();
            inReadThread.start();
            errReadThread.start();
      }

      private void processEnded(int exitValue) {
            // Handle process end..
            handler.processEnded(exitValue);
      }

      private void processNewInput(String input) {
            // Handle process new input..
            handler.processNewInput(input);
      }

      private void processNewError(String error) {
            // Handle process new error..
            handler.processNewError(error);
      }

      // Run the command and return the ExecHelper wrapper object..
      public static ExecHelper exec(ExecProcessor handler, String command) throws IOException {
            return new ExecHelper(handler, Runtime.getRuntime().exec(command));
      }

      // Print the output string through the print writer..
      public void print(String output) {
            outputWriter.print(output);
      }

      // Print the output string (and a CRLF pair) through the print writer..
      public void println(String output) {
            outputWriter.println(output);
      }

      public void run() {
            // Are we on the process Thread?
            if (processThread == Thread.currentThread()) {
                  try {
                        // This Thread just waits for the process to end and notifies the handler..
                        processEnded(process.waitFor());
                  } catch (InterruptedException ex) {
                        ex.printStackTrace();
                  }
                  // Are we on the InputRead Thread?
            } else if (inReadThread == Thread.currentThread()) {
                  try {
                        // Read the InputStream in a loop until we find no more bytes to read..
                        for (int i = 0; i > -1; i = pInputStream.read(inBuffer)) {
                              // We have a new segment of input, so process it as a String..
                              processNewInput(new String(inBuffer, 0, i));
                        }
                  } catch (IOException ex) {
                        ex.printStackTrace();
                  }
                  // Are we on the ErrorRead Thread?
            } else if (errReadThread == Thread.currentThread()) {
                  try {
                        // Read the ErrorStream in a loop until we find no more bytes to read..
                        for (int i = 0; i > -1; i = pErrorStream.read(errBuffer)) {
                              // We have a new segment of error, so process it as a String..
                              processNewError(new String(errBuffer, 0, i));
                        }
                  } catch (IOException ex) {
                        ex.printStackTrace();
                  }
            }
      }
}
//___________________________________________________________________
/* FILE: dev/exec/tester/TestApplication.java */
//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
package dev.exec.tester;

import java.awt.*;
import javax.swing.*;

public class TestApplication {
      private boolean packFrame = false;
      //Construct the application
      public TestApplication() {
            TestFrame frame = new TestFrame();
            //Validate frames that have preset sizes
            //Pack frames that have useful preferred size info, e.g. from their layout
            if (packFrame) {
                  frame.pack();
            } else {
                  frame.validate();
            }
            //Center the window
            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
            Dimension frameSize = frame.getSize();
            if (frameSize.height > screenSize.height) {
                  frameSize.height = screenSize.height;
            }
            if (frameSize.width > screenSize.width) {
                  frameSize.width = screenSize.width;
            }
            frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);
            frame.setVisible(true);
      }

      //Main method
      public static void main(String[] args) {
            try {
                  UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (Exception e) {
                  e.printStackTrace();
            }
            new TestApplication();
      }
}
//___________________________________________________________________
/* FILE: dev/exec/tester/TestFrame.java */
//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
package dev.exec.tester;

import java.awt.*;
import java.awt.event.*;
import java.io.*;

import javax.swing.*;
import javax.swing.border.*;

import dev.exec.util.*;

public class TestFrame extends JFrame implements ExecProcessor {
      private JPanel contentPane;
      private JMenuBar jMenuBar1 = new JMenuBar();
      private JMenu jMenuFile = new JMenu();
      private JMenuItem jMenuFileExit = new JMenuItem();
      private JMenuItem jMenuHelpAbout = new JMenuItem();
      private JLabel statusBar = new JLabel();
      private BorderLayout borderLayout1 = new BorderLayout();
      private JTextField jTextField1 = new JTextField();
      private JMenuItem jMenuItem1 = new JMenuItem();
      private JTextArea jTextArea1 = new JTextArea();
      private JScrollPane jScrollPane1 = new JScrollPane();
      private ExecHelper exh;
      //Construct the frame
      public TestFrame() {
            enableEvents(AWTEvent.WINDOW_EVENT_MASK);
            try {
                  jbInit();
            } catch (Exception e) {
                  e.printStackTrace();
            }
      }

      //Component initialization
      private void jbInit() throws Exception {
            contentPane = (JPanel)this.getContentPane();
            contentPane.setLayout(borderLayout1);
            this.setSize(new Dimension(400, 300));
            this.setTitle("Exec Test Frame");
            statusBar.setBorder(BorderFactory.createEtchedBorder());
            statusBar.setDebugGraphicsOptions(0);
            statusBar.setDoubleBuffered(true);
            statusBar.setOpaque(false);
            statusBar.setVerifyInputWhenFocusTarget(true);
            statusBar.setText(" Ready...");
            jMenuFile.setText("File");
            jMenuFileExit.setText("Exit");
            jMenuFileExit.addActionListener(new ActionListener() {
                  public void actionPerformed(ActionEvent e) {
                        jMenuFileExitActionPerformed(e);
                  }
            });
            jTextField1.setBackground(UIManager.getColor("control"));
            jTextField1.setBorder(BorderFactory.createCompoundBorder(new TitledBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED, Color.white, Color.white, new Color(103, 101, 98), new Color(148, 145, 140)), "Input"), BorderFactory.createEmptyBorder( -2, 0, -2, 0)));
            jTextField1.setDoubleBuffered(true);
            jTextField1.setOpaque(false);
            jTextField1.setCaretColor(Color.black);
            jTextField1.setCaretPosition(0);
            jTextField1.setText("");
            jTextField1.addActionListener(new java.awt.event.ActionListener() {
                  public void actionPerformed(ActionEvent e) {
                        inputActionPerformed(e);
                  }
            });
            contentPane.setBackground(UIManager.getColor("control"));
            contentPane.setDoubleBuffered(true);
            contentPane.setOpaque(true);
            jMenuItem1.setText("Run Command.exe");
            jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
                  public void actionPerformed(ActionEvent e) {
                        runCommandActionPerformed(e);
                  }
            });
            jTextArea1.setBackground(UIManager.getColor("control"));
            jScrollPane1.getViewport().setBackground(UIManager.getColor("control"));
            jScrollPane1.setAutoscrolls(true);
            jScrollPane1.setBorder(new TitledBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED, Color.white, Color.white, new Color(103, 101, 98), new Color(148, 145, 140)), "Output"));
            jScrollPane1.setOpaque(false);
            jTextArea1.setDoubleBuffered(true);
            jTextArea1.setOpaque(false);
            jTextArea1.setText("");
            jTextArea1.setColumns(80);
            jTextArea1.setRows(25);
            jTextArea1.setWrapStyleWord(true);
            jMenuFile.add(jMenuItem1);
            jMenuFile.add(jMenuFileExit);
            jMenuBar1.add(jMenuFile);
            setJMenuBar(jMenuBar1);
            contentPane.add(statusBar, BorderLayout.SOUTH);
            contentPane.add(jTextField1, BorderLayout.NORTH);
            contentPane.add(jScrollPane1, BorderLayout.CENTER);
            jScrollPane1.getViewport().add(jTextArea1, null);
      }

      private void updateTextArea(JTextArea textArea, String line) {
            textArea.append(line);
            textArea.setSelectionStart(textArea.getText().length());
            textArea.setSelectionEnd(textArea.getText().length());
      }

      //File | Exit action performed
      public void jMenuFileExitActionPerformed(ActionEvent e) {
            System.exit(0);
      }

      //Overridden so we can exit when window is closed
      protected void processWindowEvent(WindowEvent e) {
            super.processWindowEvent(e);
            if (e.getID() == WindowEvent.WINDOW_CLOSING) {
                  jMenuFileExitActionPerformed(null);
            }
      }

      public void processNewInput(String input) {
            updateTextArea(jTextArea1, input);
      }

      public void processNewError(String error) {
            updateTextArea(jTextArea1, error);
      }

      public void processEnded(int exitValue) {
            exh = null;
            statusBar.setText("Command.exe ended..");
            JOptionPane.showMessageDialog(this, "Exit value for Command.exe was [" + exitValue + "]", "Command.exe is done!", JOptionPane.INFORMATION_MESSAGE);
            try {
                  Thread.sleep(1000);
            } catch (InterruptedException ex) {
            }
            jTextArea1.setText(null);
            statusBar.setText("Ready..");
      }

      void runCommandActionPerformed(ActionEvent e) {
            if (exh == null) {
                  try {
                        exh = ExecHelper.exec(this, "cmd.exe");
                        statusBar.setText("Command.exe running..");
                  } catch (IOException ex) {
                        processNewError(ex.getMessage());
                  }
            }
      }

      void inputActionPerformed(ActionEvent e) {
            if (exh != null) {
                  exh.println(jTextField1.getText());
                  jTextField1.setText(null);
            }
      }
}
//___________________________________________________________________
0
 
LVL 9

Expert Comment

by:doronb
ID: 9608087
As you can see TestApplication and TestFrame simply serve GUI purposes.

ExecProcessor is an interface that includes methods needed to process INPUT/ERROR signals from the process being executed by Java code.

ExecHelper is the interesting class since it carries out the job. It first spawns the process, binds its streams and controls the threads it uses to monitor the I/O activity of the spawned process.

The way this program is designed and implemented you can substitute any other GUI instead of TestApplication and TestFrame and as long as you have an ExecProcessor responding to the process events and an ExecHelper to start the process, all will work exactly as it does in my example.

Hope this helps,
Doron
0
 
LVL 9

Expert Comment

by:doronb
ID: 9608137
I would like to add that I am sorry for not really fixing your code so that it would work.  I felt that it would be a better approach to present you with code that is modular, documented and most importantly, works in a way that would suit more than just running the DOS command line interface.

Good luck,
Doron
0
 
LVL 1

Author Comment

by:eric2405
ID: 9612252
Thanks for the comments savalou

Thanks ever so much for your help Doron.
Now I must be doing something really stupid because I can't get the program to work.
I have put the .java programs in two different packages. This is what I get when I try to compile the programs.

ExecProcessor.java
(Compiled)

ExecHelper.java
C:\dev\exec\tester\dev\exec\util\ExecHelper.java:21: cannot resolve symbol
symbol  : class ExecProcessor
location: class dev.exec.util.ExecHelper
     private ExecProcessor handler;
             ^
C:\dev\exec\tester\dev\exec\util\ExecHelper.java:23: cannot resolve symbol
symbol  : class ExecProcessor
location: class dev.exec.util.ExecHelper
     private ExecHelper(ExecProcessor ep, Process p) {
                        ^
C:\dev\exec\tester\dev\exec\util\ExecHelper.java:59: cannot resolve symbol
symbol  : class ExecProcessor
location: class dev.exec.util.ExecHelper
     public static ExecHelper exec(ExecProcessor handler, String command) throws IOException {
                                   ^
3 errors
Tool completed with exit code 1

TestFrame.java
(Compiled)

TestApplication.java
C:\dev\exec\tester\TestApplication.java:13: cannot resolve symbol
symbol  : class TestFrame
location: class dev.exec.tester.TestApplication
          TestFrame frame = new TestFrame();
          ^
C:\dev\exec\tester\TestApplication.java:13: cannot resolve symbol
symbol  : class TestFrame
location: class dev.exec.tester.TestApplication
          TestFrame frame = new TestFrame();
                                ^
2 errors
Tool completed with exit code 1

I am sorry to ask again, but please where have I gone wrong?
Thanks again Doron I really appreciate your help
Eric

0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 9

Expert Comment

by:doronb
ID: 9614464
The correct file structure of the source directory is like this:

C:.
└───dev
      └───exec
            ├───tester
            │      ├───TestApplication.java
            │      └───TestFrame.java
            └───util
                  ├───ExecHelper.java
                  └───ExecProcessor.java

Once you have all the sources in the correct directories according to the above layout, everything should compile without problems.  You could also just remove the package decleration from the code and compile it all from one source directory, this should work as well.

Hope this helps,
Doron
0
 
LVL 9

Expert Comment

by:doronb
ID: 9614489
Ummmm, yes... Directory trees do not appear so nicely here... lets see if this works better:

C:.
+-------dev
      +-------exec
            +-------tester
            |      +---TestApplication.java
            |      +---TestFrame.java
            |
            +-------util
                  +---ExecHelper.java
                  +---ExecProcessor.java
0
 
LVL 9

Expert Comment

by:doronb
ID: 9614519
Slightly better, well, the idea is that first you have the "dev" folder, within it you have the "exec" folder, with in that you have the "util" and "tester" folders.  The "util" folder contains the "ExecHelper.java" and "ExecProcessor.java" files; while the "tester" folder has the "TestApplication.java" and "TestFrame.java" files.

Sorry about this mess, I wish I'd've posted all of this in one post :)
Doron
0
 
LVL 1

Author Comment

by:eric2405
ID: 9614999
Fine it works now! That is exactly what I needed
Thank you very much indeed Doron for an excellent help
Eric
0
 
LVL 9

Expert Comment

by:doronb
ID: 9615704
You're welcome :)
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Java had always been an easily readable and understandable language.  Some relatively recent changes in the language seem to be changing this pretty fast, and anyone that had not seen any Java code for the last 5 years will possibly have issues unde…
Introduction This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:
The viewer will learn how to implement Singleton Design Pattern in Java.

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now