Powershell as a java process on a unix system, output not displayed from cmdlet

46
August 21, 2019, at 04:30 AM

I am writing an implementation for a powershell client. This implementation is in java. The JVM is running on a UNIX system. I need to be able to create an object PowerShellClient and have it spawn a process that opens powershell and allows me access to its stdin, stdout, and stderr so that I can invoke commands in said powershell session and observe their output.

I have already tried jpowershell and this implementation works great, but has a limitation: If you try to invoke a cmdlet that writes output multiple times, all of the output is not obtained, and the output is not entirely read. It seems to be terminated after the first Write-Output

        PowerShell pwsh = PowerShell.openSession();
        String out = pwsh.executeCommand(
            "for($i=0; $i -lt 10; $i++){Write-Output $i; Start-Sleep -Seconds 1}")
            .getCommandOutput();
        System.out.println(out);

Produces the following:

0

So. I took it upon myself to implement something, I decided to implement it in such a way that it would wait for the prompt >>> to appear in STDOUT. Only when the prompt is seen will reading be stopped, and another command allowed to execute. However, I already have a Problem: Output from cmdlets that output powershell objects is not even seen in stdout. Here is some code

import java.io.*;
import java.util.concurrent.Semaphore;
public class PowerShellClient {
    private PrintWriter stdin;
    private BufferedReader stderr;
    private BufferedReader stdout;
    private Process powerShellProcess;
    private Thread readErrThread;
    private Thread readOutThread;
    public PowerShellClient() throws IOException {
        powerShellProcess = new ProcessBuilder("powershell", "-nol", "-noe").start();
        stdout = new BufferedReader(
            new InputStreamReader(powerShellProcess.getInputStream()));
        stderr = new BufferedReader(
            new InputStreamReader(powerShellProcess.getErrorStream()));
        stdin = new PrintWriter(
            new OutputStreamWriter(
                new BufferedOutputStream(
                    powerShellProcess.getOutputStream())),
                    true);
        readOutThread = new Thread(() -> {
            String line;
            try {
                while ((line = stdout.readLine()) != null)
                    System.out.println("[STDOUT]: " + line);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        readErrThread = new Thread(() -> {
            String line;
            try {
                while(null != (line = stderr.readLine()))
                    System.out.println("[STDERR]: " + line);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        readErrThread.start();
        readOutThread.start();
    }
    public void executeCommand(String aRawCmd) {
        stdin.println(aRawCmd);
    }
}

And the use case:

PowerShellClient client = new PowerShellClient();
client.executeCommand("Get-Process");

Produces the following:

[STDOUT]: >>> Get-Process
[STDOUT]: 
[STDOUT]: 

while this use case:

PowerShellClient client = new PowerShellClient();
client.executeCommand("for($i=0; $i -lt 10; $i++) { Write-Output $i; Start-Sleep 1}");

produces the following:

[STDOUT]: >>> for($i=0; $i -lt 10; $i++) { Write-Output $i; Start-Sleep 1}
[STDOUT]: 0
[STDOUT]: 1
[STDOUT]: 2
[STDOUT]: 3
[STDOUT]: 4
[STDOUT]: 5
[STDOUT]: 6
[STDOUT]: 7
[STDOUT]: 8
[STDOUT]: 9

My Question is this: Why is this happening? What is causing the output not to be observed, from a cmdlet that normally produces 10s of lines of output? I think it has something to do with the fact that the output from the cmdlets are passed to the powershell object engine, which somehow determines the size of your terminal and will format the output. I have already tried piping to Out-String, Write-Out, and Write-Host. I've even tried redirecting output to a file and then cating that file. No cigar, the file has no contents (except for a new \n).

Am I missing some configuration or something?

Version of powershell installed on UNIX system: PowerShell 6.2.2

READ ALSO
“[ERROR] duplicate entry: META-INF/MANIFEST.MF” shows up when using IntelliGuard to compile

“[ERROR] duplicate entry: META-INF/MANIFEST.MF” shows up when using IntelliGuard to compile

I'm trying to use IntelliGuard plugin in IntelliJ to compile and obfuscate my jar file, but "[ERROR] duplicate entry: META-INF/MANIFESTMF " shows up when I try to build in the "Build -> Obfuscate module" window

42
Java Data Communications Frameworks and Technologies [on hold]

Java Data Communications Frameworks and Technologies [on hold]

What are some Java data communications frameworks and technologies that are available today? What do you like about it? What do you dislike about it? What features do you wish it had (eg

38
How to dynamically call a variable based on another variable in java

How to dynamically call a variable based on another variable in java

I have an assignment and to simplify the code I would like to be able to reference a String based on the value of an int

23