Franklin
Franklin

Reputation: 1801

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. I'm trying to get the script's output and put it into a JTextArea within the GUI. 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.

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.

#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.

Upvotes: 4

Views: 2298

Answers (4)

tias
tias

Reputation: 1

This helped me: Do not read the InputStream if there are no errors. e.g.

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 ();
    }
}

Upvotes: 0

Tim
Tim

Reputation: 91

I was having the same issue. I moved the proc.getOutputStream().close() before the while loop and everything worked

Upvotes: 3

Jason Pyeron
Jason Pyeron

Reputation: 2528

Here is my tested code, note the choice to "hack" or close STDIN when done.

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();
    }
}

Upvotes: 0

Louis Ricci
Louis Ricci

Reputation: 21086

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
  • Check the ErrorStream
  • Use Process.waitFor() read the java-docs for the Process class.
  • 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)

NOTE the code above isn't tested, so there may be syntax errors etc etc.

Upvotes: 1

Related Questions