Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4251454

Redirection not possible with Runtime.exec()

XMLWordPrintable

    • b02
    • x86
    • windows_nt



      Name: mf23781 Date: 07/02/99


      Test Case and Failure Data:

               Description of Problem:
                      The user was trying to issue an command and redirect the output to a file.
                      Issuing a runtime exec with one of the following commands will cause a problem
                        cmd /c netstat > myfile for example. myfile would be created but would be empty.
                        
                      An internal command such as dir, for example cmd /c dir > myFile will work
                      as excepted, myfile would contain the directory listing.
                      
                      The problem was not present in JDK1.2.x. Looking at the source code showed only
                      one difference. This was a change to the flags in the CreateProcess
                      call. DETATCHED_PROCESS was changed to 0. (normal process). This allows the redirection
                      to occur as expected.
                      
                      We attempted to put this fix into 1.7.1. This generates a problem in that for jrew a console
                      window will appear. This also occurs with JDK1.2.2. The latest drop of Kestrel has no changes
                      in the source code. (This is Sunbug 4188007)
                      
                      Ways of preventing this have been investigated. This involded creating a console
                      but not showing it. Use the CREATE_NEW_CONSOLE flag but set the wShowWindow flag to SW_HIDE.
                      However for GUI applications this blocks the interface all together.
            
               Problem Analysis:
                      
                      A change was made so that the child process was nolonger DETATCHED_PROCESS. This fixes
                      the redirection problem and also has some effect on the running of 16 bit applications. SunBug
                      4079419 indicates that the change from DETATCHED_PROCESS to 0 was made in 1.2beta4 to enable
                      16 bit applications to be run.
                      
                      This change also allows the redirection to occur successfully. It generates the console window
                      generation problem.
                      
                      Abstracting away from the JVM, how is it possible to create the process (allowing for 16bit
                      applications/redirection) and preventing the console window from appearing for console applications
                      when run from a Windows Application. javaw or jrew are the same as the non-w counterparts
                      except that they are linked differently. javaw is linked with -subsystem:windows java is linked
                      with -sunsystem:console.
                      
            
               Test Case:
                     To deal with the problem, some code is required that can execute any external command.
                     The code below will execute the first command line arguement sending the data from the file
                     specifed in the second arguement. This filename is optional.
                     
      ----------------------------------Start of test case ---------------------------------------------------------

      // IBM Java Technology Centre
      // Matthew B White
      // Please note that this code is offered with no warranty
      // and is offered for examples only!
      import java.io.*;

      public class StoreExec {

          // Main functions
          // First cmd line arg = command to run
          // Second is the file to send to the stdin [optional]
          public static void main (String[] args)
          {
              try {

                  // Create threads to process the stdin/stdout/stderr of the
                  // process.
                  ExecStorage stdoutStorage;
                  ExecStorage stderrStorage;
                  Write fromFile;

                  if (args.length != 1 && args.length != 2) {
                      System.out.println("Correct Usage is ");
                      System.out.println("\t java StoreExec <command> [<filename>]");
                      System.out.println("\t <command> The command to execute- double");
                      System.out.println("\t quotes if it contains spaces");
                      System.out.println("\t <filename> Name of the file to send to the ");
                      System.out.println("\t stdin of the command - optional");
                      System.exit(1);

                  }


                  // Set up command, arguments, and environment variables
                  String prog = args[0];
                  
                  // get the runtime object
                  Runtime rt = Runtime.getRuntime();

                  System.out.println("Execing the process... "+prog);

                  // execute the processes
                  Process p = rt.exec(prog);

                  // Running the storage thread for the stdout of the command
                  stdoutStorage = new ExecStorage(p.getInputStream());
                  stdoutStorage.start();

                  // Running the storage thread for the stderr of the command
                  stderrStorage = new ExecStorage(p.getErrorStream());
                  stderrStorage.start();


                  // if an arguement has been specified than feed that data
                  // to the stdin of the command
                  if (args.length==2) {
                  
                     fromFile = new Write(args[1],p.getOutputStream());
                     fromFile.start();
                  }

                  // Wait for the process to finish and get the return code
                  int s = p.waitFor();


                  // wait for all the data to be read - should be
                  // synchronised on the multiple threads
                  System.out.println("Sleeping....");
                  Thread.sleep(1000);

                  // Dispaly the return value and the data captured from the process
                  System.out.println("\n\nProcess Finished - Return value from process = "+s);
                  System.out.println("Data from the command is on the next lines");
                  String lines[] = stdoutStorage.extract();
                  for (int count=0; count<lines.length; count++) {
                      System.out.println("stdout>>>"+lines[count]);
                  }

                  System.out.println("\n\n");

                  String lines2[] = stderrStorage.extract();
                  for (int count=0; count<lines2.length; count++) {
                      System.out.println("stderr>>>"+lines2[count]);
                  }


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


      // Reads in from a file and sends to the process
      class Write extends Thread {

          String filename;
          OutputStream out;

          public Write(String filename,OutputStream out)
          {
              this.filename = filename;
              this.out=out;
          }

          public void run()
          {

              try {
                  FileReader inputfile = new FileReader(filename);
                  BufferedReader buffered = new BufferedReader(inputfile);
                  PrintWriter writer = new PrintWriter(out);


                  String line;
                  while ( (line = buffered.readLine()) != null) {
                      writer.println(line);
                  }

                  buffered.close();
                  writer.close();

              } catch (IOException e)
                  {

                      e.printStackTrace();
                  }

              }
          

      }

      // Read from the InputStream specified and store
      class ExecStorage extends Thread {

          // Storage for the data returned from the command
          java.util.Vector lines;
          //The input stream from the process to handle
          InputStream is;


          // Store the process
          public ExecStorage(InputStream is)
          {
              this.is=is;
          }

          // Normal run method of the thread
          // Will get the input stream from the process
          // and read data until there is no more data to read.
          public void run()
          {
              // use the stream specified from the constructor
              InputStreamReader isr = new InputStreamReader(is);
              BufferedReader br = new BufferedReader(isr);

              // The line to read
              String line;

              // Setup the vector to hold the data
              // Set the inital size of the vector if you know how much data
              // will be comming - would help to improve performance as the
              // vector will not have to expand its size.
              lines = new java.util.Vector();



              // System.out.print("\nEvery dot is another line read>");
              try {

                  // read from the buffered reader until nothing more exists
                  while ( ( line=br.readLine()) != null) {
                      // add this to the vector
                      //System.out.print(".");
                      lines.addElement(line);
                  }

                  br.close();

              } catch (java.io.IOException e) {
                  e.printStackTrace();
              }

          }

          // Copy the vector to a string array
          // for printing out
          public String[] extract()
          {
              String data[] = new String[lines.size()];
              lines.copyInto(data);

              return data;
          }


      }
      -------------------------- end of test case ---------------------------------

      (Review ID: 85121)

      ======================================================================

            duke J. Duke
            miflemi Mick Fleming
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: