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

与从Java应用程序调用的Powershell进程交互,java,powershell,process,Java,Powershell,Process,我正在尝试运行一个Java应用程序,它在启动时创建一个新的powershell进程,然后在以后与它进行多次交互。调用powershell.exe并让它执行单个命令并返回输出对我来说很好。如果我不希望powershell进程立即完成/退出,而是保持打开状态,以便写入其outputStream并从inputStream接收结果,则会出现问题 String input = "dir"; String[] commandList = {"powershe

我正在尝试运行一个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<String> output = outGobbler.getOuput(); 
                input = ""; 
                for(String o: output) { 
                        input += o; 
                } 

            System.out.println("Final Output:"); 
            System.out.println(input); 
这没有任何效果-当我运行代码时,不会显示第二个dir输出。我还尝试使用powershell.exe选项打开powershell,但不立即关闭:

String[] commandList = {"powershell.exe", "-NoExit", "-Command", "dir"};
但是我的代码挂起了,这意味着使用进程的inputStream的Gobbler不读取任何内容-奇怪的是:他们甚至不读取第一行-必须至少有一些输出

我还尝试在写入第二个“dir”命令后关闭进程的outputStream,但没有改变任何内容

非常感谢您的帮助。 谢谢
Kurt

这听起来与另一个过程所产生的过程的性质差不多。我觉得你的行为很标准

这是关键:
p.waitFor()

来自Java文档:

如有必要,使当前线程等待,直到此进程对象表示的进程终止

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

如果从Sysinternals运行,您将能够看到Java进程启动了一个子PowerShell进程


所以我不认为你能像记忆中的活物体一样与它互动

谢谢你,安迪。那么调用powershell.exe和cmd.exe之间肯定有区别。因为当我将命令更改为:
String[]commandList={“cmd.exe”、“/k”、“dir”}我实际上可以将另一个“dir”命令写入cmd.exe并获取其反馈。因此在这个场景中,我保持cmd.exe运行(/k开关),并可以向它发送后续命令。我无法对powershell.exe执行相同的操作?@Kurt当您让cmd.exe运行第二个命令时,您是否再次使用
pb.start()
运行它?如果是这样的话,我想你可能正在编写另一个cmd.exe。为了确保使用ProcExp查看进程树,以便更好地了解幕后发生的事情。不,我使用了与上面完全相同的代码,无需再次调用pb.start()。当我运行代码时,我可以看到一个cmd.exe和一个conhost.exe正在打开,而不是两个。在输出中,您还可以看到我的第二个“dir”命令被输入到open cmd.exe中:以下是缩写输出:C:\Users\k\Documents\Eclipse Workspace\PipeRedirection目录C:\Users\k\Documents\Eclipse Workspace\PipeRedirection>C:\Users\k\Documents\Eclipse Workspace\PipeRedirection目录最后一个建议,尝试通过cmd.exe间接调用powershell:
cmd.exe/k powershell.exe-command dir
String[] commandList = {"powershell.exe", "-NoExit", "-Command", "dir"};