2

is there some way on how to open powershell with process builder in javafx and keep it opened to execute any command anytime?

Example code(executing only one command at a time):

try {
    ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", "powershell -Command \"Add-Type -AssemblyName System.DirectoryServices.AccountManagement; [System.DirectoryServices.AccountManagement.UserPrincipal]::Current.DisplayName\"&&exit");
    Process p = builder.start();
    BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
    String line = null;
    while ((line = reader.readLine()) != null) {
        if (!line.trim().isEmpty()) {
            displayname = line;
        }
    }
    reader.close();
    p.waitFor();
    p.destroy();

} catch (IOException | InterruptedException ex) {
    Logger.getLogger(AccountStatus.class.getName()).log(Level.SEVERE, null, ex);
}

Reason to keep it opened: loading powershell takes maybe 3 seconds and loading for example active directory plugin takes another maybe 2 seconds everytime i want to execute some command. If there is some way on how to preload powershell and send command to processbuilder anytime it would be very helpfull, thanks for advices.

EDIT:

I have found solution here: Apache Commons exec PumpStreamHandler continuous input

Thanks to MichalVales!

With this quick sample i am able to open powershell, keep it opened, preload some module and execute any new command anytime without loading all again.

public class FXMLDocumentController implements Initializable {

private BufferedWriter writer;

@FXML
private void handleButtonAction(ActionEvent event) {

    try {
        writer.write("Import-Module ActiveDirectory -Cmdlet Get-ADUser\n");
        writer.flush();
    } catch (IOException ex) {
        Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
    }

}

@FXML
private void handleButtonAction2(ActionEvent event) {
    try {
        writer.write("Get-ADUser somenamehere -Properties * | Select-Object LockedOut\n");
        writer.flush();
    } catch (IOException ex) {
        Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
    }
}

@Override
public void initialize(URL url, ResourceBundle rb) {

    ProcessBuilder builder = new ProcessBuilder("powershell.exe");
    Process process;
    try {
        process = builder.start();
        writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
        StreamReader outputReader = new StreamReader(process.getInputStream(), System.out);
        outputReader.start();
        StreamReader err = new StreamReader(process.getErrorStream(), System.err);
        err.start();
    } catch (IOException ex) {
        Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
    }

}

}

StreamReader code can be found on link from MichalVales

EDIT2:

I was trying to pass czech characters with any writer, but without success. I think that its impossible to pass czech characters like "ěščřžýáíé" to powershell without changing system locale, but i dont want to do it. I have tried processbuilder, apache exec, all failed, but i have found super library which works and is really easy to use: jPowerShell

So if you have problems with keeping powershell alive or problem with characters, this is the best solution.

zuby33
  • 51
  • 4
  • 2
    Why not just launch PowerShell as a `Process` and keep the `Process` open? You'd then [send commands](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Process.html#getOutputStream()) and [read the results](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Process.html#getInputStream()) and/or [the errors](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Process.html#getErrorStream()). – Slaw Feb 07 '19 at 00:31
  • Indeed, pulling cmd in here seems unnecessarily complicated. – Joey Feb 22 '19 at 09:41

0 Answers0