简体   繁体   English

尝试调用powershell脚本时,Java程序挂起

[英]Java program hangs when trying to invoke powershell script

I'm building a GUI with NetBeans, and one of the buttons in the GUI requires the use of a powershell script. 我正在使用NetBeans构建GUI,GUI中的一个按钮需要使用powershell脚本。 I'm trying to get the script's output and put it into a JTextArea within the GUI. 我正在尝试获取脚本的输出并将其放入GUI中的JTextArea。 Here is what I have so far. 这是我到目前为止所拥有的。 I did a bit of debugging, and it seems to hang inside the while loop, but I'm confused as to why it's doing so. 我做了一些调试,它似乎挂在while循环中,但我很困惑为什么它这样做。

private void runButtonActionPerformed(java.awt.event.ActionEvent evt) {                                          
    try {
        Runtime runtime = Runtime.getRuntime();
        Process proc = runtime.exec("cmd powershell C:/hello1.ps1");
        InputStream is = proc.getInputStream();
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader reader = new BufferedReader(isr);
        String line;
        while ((line = reader.readLine()) != null) {
            outputTextArea.setText(line);
        }
        reader.close();
        proc.getOutputStream().close();
    } catch (IOException ex) {
        Logger.getLogger(BatchFrame.class.getName()).log(Level.SEVERE, null, ex);
    }
}

And here is a simple powershell script I'm trying to get it to work with. 这是一个简单的PowerShell脚本,我试图让它与之合作。

#Filename: hello1.ps1
Write-Host "Hello World!"
#End of Script

I did some researched, and I noticed that it was hanging for other people to, but only because they forgot to close the processes output stream. 我做了一些研究,我注意到它是挂给其他人的,但只是因为他们忘了关闭进程输出流。

I was having the same issue. 我遇到了同样的问题。 I moved the proc.getOutputStream().close() before the while loop and everything worked 我在while循环之前移动了proc.getOutputStream()。close(),一切正常

private void runButtonActionPerformed(java.awt.event.ActionEvent evt) {      
    String allOutput = "";                                
    try {
        Runtime runtime = Runtime.getRuntime();
        Process proc = runtime.exec("cmd /c powershell C:/hello1.ps1");
        BufferedReader errorReader = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
        BufferedReader outReader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
        String line;
        while ((line = errorReader.readLine()) != null) {
            allOutput += "\n" + line;
        }
        while ((line = outReader.readLine()) != null) {
            allOutput += "\n" + line;
        }
        int retVal = proc.waitFor();
    } catch (IOException ex) {
        Logger.getLogger(BatchFrame.class.getName()).log(Level.SEVERE, null, ex);
    }
    outputTextArea.setText(allOutput);
}
  • Form the command line properly with CMD.EXE /c 使用CMD.EXE / c正确地形成命令行
  • Check the ErrorStream 检查ErrorStream
  • Use Process.waitFor() read the java-docs for the Process class. 使用Process.waitFor()读取Process类的java-docs。
  • No need to close the OutputStream since you never use it and the program shouldn't expect user input (java switching the names of input and output is annoying) 不需要关闭OutputStream,因为你从不使用它,程序不应该期望用户输入(java切换输入和输出的名称很烦人)

NOTE the code above isn't tested, so there may be syntax errors etc etc. 注意上面的代码没有经过测试,因此可能存在语法错误等。

Here is my tested code, note the choice to "hack" or close STDIN when done. 这是我测试过的代码,注意完成后“破解”或关闭STDIN的选择。

package test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class Test
{
    private static boolean hack=false;

    public static void main(String[] args) throws IOException
    {
        Runtime rt = Runtime.getRuntime();

        String cmd[];

        if (hack)
            cmd=new String[]{"cmd","/c","C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\powershell.exe","-File","c:\\cygwin\\home\\jpyeron\\test.ps1", "<NUL"};
        else
            cmd=new String[]{"C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\powershell.exe","-File","c:\\cygwin\\home\\jpyeron\\test.ps1"};

        final Process p = rt.exec(cmd);

        Thread stdout = new Thread()
        {
            public void run() 
            {
                InputStream out = p.getInputStream();
                BufferedReader in = new BufferedReader(new InputStreamReader(out)); 
                String line = null; 
                try
                {
                    while ((line = in.readLine()) != null) 
                    { 
                        System.out.println(line); 
                    }
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }              
            };
        };
        stdout.start();

        Thread stderr = new Thread()
        {
            public void run() 
            {
                InputStream err = p.getInputStream();
                BufferedReader in = new BufferedReader(new InputStreamReader(err)); 
                String line = null; 
                try
                {
                    while ((line = in.readLine()) != null) 
                    { 
                        System.out.println(line); 
                    }
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }                
            };
        };
        stderr.start();

        if (hack)
            ;
        else
            p.getOutputStream().close();
    }
}

This helped me: Do not read the InputStream if there are no errors. 这有助于我:如果没有错误,请不要读取InputStream。 eg 例如

private void takeAction () throws IOException, InterruptedException
{
    String action = getAction (); // A powershell-Command
    Process p = Runtime.getRuntime ().exec ( action );

    InputStream is = p.getErrorStream ();
    if ( 0 < is.available () )
    {
        BufferedReader br = new BufferedReader (
                new InputStreamReader ( is ) );
        String err = br.readLine ();
        while ( null != err )
        {
            System.out.println ( "takeAction() " + err );
            err = br.readLine ();
        }
        p.getOutputStream ().close ();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM