2012-01-05 13 views
6

Estoy tratando de ejecutar una aplicación Java que crea un nuevo proceso de PowerShell al inicio y luego interactúa con él varias veces. Llamar a powershell.exe y hacer que ejecute un solo comando y devolver la salida funciona bien para mí. El problema surge si no quiero que el proceso de PowerShell termine/salga inmediatamente, sino que permanezca abierto para poder escribir en su outputStream y recibir los resultados de InputStream.Interactuar con el proceso Powershell llamado desde la aplicación Java

  String input = "dir"; 

      String[] commandList = {"powershell.exe", "-Command", "dir"}; 

      ProcessBuilder pb = new ProcessBuilder(commandList); 

      Process p = pb.start(); 

      if(input != null) { 
       PrintWriter writer = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(p.getOutputStream())), true); 
       writer.println(input); 
       writer.flush(); 
       writer.close(); 

      } 

      //p.getOutputStream().close(); 

      Gobbler outGobbler = new Gobbler(p.getInputStream()); 
      Gobbler errGobbler = new Gobbler(p.getErrorStream()); 
      Thread outThread = new Thread(outGobbler); 
      Thread errThread = new Thread(errGobbler); 
      outThread.start(); 
      errThread.start(); 

      System.out.println("Waiting for the Gobbler threads to join..."); 

      outThread.join(); 
      errThread.join(); 

      System.out.println("Waiting for the process to exit...");                   

       int exitVal = p.waitFor(); 
       System.out.println("\n****************************"); 
       System.out.println("Command: " + "cmd.exe /c dir"); 
       System.out.println("Exit Value = " + exitVal); 
       List<String> output = outGobbler.getOuput(); 
       input = ""; 
       for(String o: output) { 
         input += o; 
       } 

      System.out.println("Final Output:"); 
      System.out.println(input); 

Este código devuelve el resultado del comando "dir" de un powershell - bien. Pero como se puede ver, estoy tratando de ejecutar un segundo comando "dir" usando

   PrintWriter writer = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(p.getOutputStream())), true); 
       writer.println(input); 
       writer.flush(); 

Esto no tiene ningún efecto en absoluto - no hay segunda salida dir se muestra cuando corro mi código. También he experimentado con una opción para abrir el powershell.exe PowerShell pero no cerrarla de inmediato:

String[] commandList = {"powershell.exe", "-NoExit", "-Command", "dir"}; 

Pero entonces mis cuelga de código, es decir, de que consumen flujoEntrada del proceso no lee nada del pavo - curiosamente : ni siquiera leen la primera línea, debe haber al menos alguna salida ...

También traté de cerrar el outputStream del proceso después de escribir el segundo comando "dir" en él - no lo hice Cambia cualquier cosa.

Cualquier ayuda es muy apreciada. Gracias Kurt

Respuesta

0

Esto suena bien para la naturaleza de un proceso generado por otro proceso. Creo que estás experimentando un comportamiento bastante estándar.

Esta es la clave: p.waitFor()

a partir de documentos de Java:

hace que el hilo actual que esperar, si es necesario, hasta que el proceso representado por este objeto de proceso ha terminado.

No podrá recibir el flujo de salida de PowerShell hasta que haya finalizado. Cuando se ejecuta con -NoExit, nunca sale, y es por eso que está experimentando el bloqueo.

Si ejecuta ProcExp desde Sysinternals, podrá ver su proceso de Java ejecutar un proceso secundario de PowerShell.

Así que no creo que puedas interactuar con él como si fuera un objeto vivo en la memoria.

+0

Gracias Andy. Entonces debe haber una diferencia entre llamar powershell.exe y cmd.exe. Porque cuando cambio el comando a esto: 'String [] commandList = {" cmd.exe ","/k "," dir "};' De hecho, puedo escribir otro comando "dir" al cmd.exe y obtener su retroalimentación. Por lo tanto, en este escenario, mantengo el cmd.exe en ejecución (modificador/k) y puedo enviarle los comandos subsiguientes. ¿De ninguna manera puedo hacer lo mismo con powershell.exe? – Kurt

+0

@Kurt Cuando tienes cmd.exe ejecuta un segundo comando ¿lo estás ejecutando con 'pb.start()' de nuevo? Si es así, creo que podría estar girando otro cmd.exe. Para asegurarse de ver el árbol de procesos con ProcExp para obtener una mejor visión de lo que está sucediendo detrás de las escenas. –

+0

no, uso exactamente el mismo código que el anterior, sin una segunda llamada a pb.start(). Cuando ejecuto el código, puedo ver una apertura de cmd.exe y una de conhost.exe, no dos. En la salida también puede ver que mi segundo comando "dir" se ingresa en el cmd abierto.exe: – Kurt

Cuestiones relacionadas