【问题标题】:Interact with Powershell process called from Java application与从 Java 应用程序调用的 Powershell 进程交互
【发布时间】:2012-02-03 03:16:50
【问题描述】:

我正在尝试运行一个 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); 

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

运行第二个“dir”命令
                PrintWriter writer = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(p.getOutputStream())), true); 
                writer.println(input); 
                writer.flush(); 

这没有任何效果 - 当我运行我的代码时没有显示第二个目录输出。我还尝试了一个 powershell.exe 选项来打开 powershell 但不立即关闭它:

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

但是随后我的代码挂起,这意味着使用进程的 inputStream 的 Gobbler 不读取任何内容 - 奇怪的是:他们甚至不读取第一行 - 必须至少有一些输出......

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

非常感谢任何帮助。 谢谢 库尔特

【问题讨论】:

    标签: java powershell process


    【解决方案1】:

    这听起来很适合由另一个进程启动的进程的性质。我认为您的行为非常标准。

    这是关键:p.waitFor()

    来自 Java 文档:

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

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

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

    所以我认为你不能像它是内存中的活体一样与之交互。

    【讨论】:

    • 谢谢安迪。那么调用powershell.exe和cmd.exe肯定是有区别的。因为当我确实将命令更改为:String[] commandList = {"cmd.exe", "/k", "dir"}; 我实际上可以向 cmd.exe 编写另一个“dir”命令并获得它的反馈。因此,在这种情况下,我保持 cmd.exe 运行(/k 开关)并可以向其发送后续命令。我不能对 powershell.exe 做同样的事情吗?
    • @Kurt 当您让 cmd.exe 运行第二个命令时,您是否再次使用pb.start() 运行它?如果是这样,我认为您可能正在启动另一个 cmd.exe。确保使用 ProcExp 观察进程树,以更好地了解幕后发生的事情。
    • 不,我使用与上面完全相同的代码 - 没有第二次调用 pb.start()。当我运行代码时,我可以看到一个 cmd.exe 和一个 conhost.exe 打开 - 而不是两个。在输出中你还可以看到我的第二个“dir”命令被输入到打开的 cmd.exe 中:
    • 这里是缩写输出: Directory of C:\Users\k\Documents\Eclipse Workspace\PipeRedirection <...contents of directory...> C:\Users\k\Documents\Eclipse Workspace\PipeRedirection>dir C:\Users\k\Documents\Eclipse Workspace\PipeRedirection 的目录 <...>
    • 最后一个建议,尝试通过 cmd.exe 间接调用 powershell:cmd.exe /k powershell.exe -command dir
    猜你喜欢
    • 2015-05-31
    • 1970-01-01
    • 1970-01-01
    • 2011-11-24
    • 2010-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-28
    相关资源
    最近更新 更多