与从Java应用程序调用的Powershell进程交互

我正在尝试运行一个Java应用程序,它在启动时创建一个新的PowerShell进程,然后再多次与它进行交互。 调用powershell.exe并让它执行单个命令并返回输出对我来说很好。 如果我不希望powershell进程立即完成/退出但是保持打开以便我可以写入其outputStream并从inputStream接收结果,则会出现问题。

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 output = outGobbler.getOuput(); input = ""; for(String o: output) { input += o; } System.out.println("Final Output:"); System.out.println(input); 

此代码从powershell返回“dir”命令的结果 – 很好。 但正如你所看到的,我正在尝试使用第二个“dir”命令

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

这没有任何影响 – 运行我的代码时没有显示第二个dir输出。 我还尝试使用powershell.exe选项打开powershell但不立即关闭它:

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

但是后来我的代码挂了,这意味着吞噬进程的inputStream的Gobbler没有读任何东西 – 奇怪的是:他们甚至没有读过第一行 – 必须至少有一些输出….

我也尝试在向第二个“dir”命令写入后关闭进程的outputStream – 没有改变任何东西。

任何帮助都非常感谢。 谢谢Kurt

这听起来适合于另一个流程旋转的流程的性质。 我认为你正在经历非常标准的行为。

这是关键: p.waitFor()

来自Java文档:

如果需要,导致当前线程等待,直到此Process对象表示的进程终止。

在终止之前,您将无法接收PowerShell输出流。 当您使用-NoExit运行时,它永远不会退出,这就是您遇到挂起的原因。

如果您从Sysinternals运行ProcExp ,您将能够看到您的Java进程启动子PowerShell进程。

所以我认为你不能像它在内存中的活动对象那样与它交互。