6

Are you aware of some Java APIs/Libraries for remote PowerShell invocation?

From this API I need things like:

  • Authentication
  • PowerShell Scripts execution
  • Getting results of scripts
7
  • Check this link: social.technet.microsoft.com/Forums/office/en-US/… At the very end of this there is a working example including error handling. Commented Apr 28, 2016 at 8:00
  • Thanks but it's not enough , I have to log in, and execute remote script; For example I will run code on my Ubuntu -> connect to Windows machine -> execute script on this machine -> get result of executing back. Although, thank you Commented Apr 28, 2016 at 8:10
  • Possibly related: serverfault.com/questions/638659/… Commented Jul 19, 2016 at 16:25
  • github.com/xebialabs/overthere - powers some of the "CI-CD" tools.. OT: Your requirement could be addressed via tools like xebialabs.com/products/xl-deploy or rundeck. Commented Jul 22, 2016 at 3:00
  • 1
    I've been searching for weeks, and I don't think there is a Java Library for connecting to another machine using RDP. You can connect a JVM to JVM, but not JVM to RDP. Commented Jul 25, 2016 at 21:56

5 Answers 5

3

You can use JPowerShell library: https://github.com/profesorfalken/jPowerShell

PowerShell powerShell = null;
try {
    //Creates PowerShell session
    PowerShell powerShell = PowerShell.openSession();
    //Increase timeout to give enough time to the script to finish
    Map<String, String> config = new HashMap<String, String>();
    config.put("maxWait", "80000");

    //Execute script
    PowerShellResponse response = powerShell.configuration(config).executeScript("./myPath/MyScript.ps1");

    //Print results if the script
    System.out.println("Script output:" + response.getCommandOutput());
} catch(PowerShellNotAvailableException ex) {
    //Handle error when PowerShell is not available in the system
    //Maybe try in another way?
} finally {
    //Always close PowerShell session to free resources.
    if (powerShell != null)
        powerShell.close();
}
Sign up to request clarification or add additional context in comments.

1 Comment

I don't see any remote execution of script in your answer. Question is asking for remote execution of script.
1

If you want to execute remotely something through Java it is nice thing to consider RMI. I do not know if You would like to keep the login (is it needed to use different users?), but this method keeps working if you change your windows password etc. There are ways to keep it secure too (but in a home environment it is not that necessary). To the shell call I recommend to use is Apache Commons Exec (ExecuteWatchdog) to build a robust solution.

Long story short: You could bypass login with this and keep a somehow portable solution.

2 Comments

I will try your solution and yes it's needed to use different users.
In PowerShell You are able to switch users. Get it as a parameter and it will be able to do the magic for you.
1

use winrm4j: https://github.com/cloudsoft/winrm4j

winrm4j is a project which enables Java applications to execute batch or PowerShell commands on a remote Windows server using WinRM

WinRmClientContext context = WinRmClientContext.newInstance();

WinRmTool tool = WinRmTool.Builder.builder("my.windows.server.com", "Administrator", "pa55w0rd!")
    .authenticationScheme(AuthSchemes.NTLM)
    .port(5985)
    .useHttps(false)
    .context(context)
    .build();

tool.executePs("echo hi");

context.shutdown();

Comments

0

You could try ProcessBuilder and redirect the output stream, like this:

Compiled with javac 1.8.0_60 and ran with: java version "1.8.0_91"

import java.util.*;
import java.io.*;
public class Test {
    public static void main(String ... args) {
        try {
            ProcessBuilder launcher = new ProcessBuilder();
            Map<String, String> environment = launcher.environment();
            launcher.redirectErrorStream(true);
            launcher.directory(new File("\\\\remote_machine\\Snaps\\"));
            launcher.command("powershell.exe", ".\\Script.ps1");
            Process p = launcher.start(); // And launch a new process
            BufferedReader stdInput = new BufferedReader(new
            InputStreamReader(p.getInputStream()));
            String line;
            System.out.println("Output :");
            while ((line = stdInput.readLine()) != null) {
                System.out.println(line);
            }
        } catch (Exception e){
           e.printStackTrace();
        }
    }
}

My Script.ps1 was a for testing, it was simple file that prints to the output stream:

Write-Host 'Hello World!'

1 Comment

It's not good idea. Isn't secured. If machine needs credentials to do some staff your variant is bad.
0
+50

Hello I have not tried this specifically with PowerShell but I have tried it with Batch files and Windows Shell Host. An alternative to using RMI is to use the windows provided remoting capabilities DCOM. This way you will not need to deploy an extra remote service on the windows machine. Instead you can use the DCOM server provided by each windows machine. The windows machine exposes something called Windows Shell Host. This windows shell host can be used to execute scripts remotely. Since almost everything in Windows comes in the form of COM objects my expectation is that Powershell as well comes as a registered COM service that you need to just find out.

In this link you will find a solution to your problem using Windows Shell Host and J-interop as a Java implementation of the DCOM protocol : How to call a remote bat file using jinterop

/ Create a session
JISession session = JISession.createSession(<domain>, <user>, <password>);
session.useSessionSecurity(true);

// Execute command
JIComServer comStub = new JIComServer(JIProgId.valueOf("WScript.Shell"),<IP>, session);
IJIComObject unknown = comStub.createInstance();
final IJIDispatch shell =     (IJIDispatch)JIObjectFactory.narrowObject((IJIComObject)unknown.queryInterface(IJIDispatch.I ID));
JIVariant results[] = shell.callMethodA("Exec", new Object[]{new JIString("%comspec% /c asadmin.bat" )});

If you need the output from the batch you can use StdOut to read it.

JIVariant stdOutJIVariant = wbemObjectSet_dispatch.get("StdOut"); 
IJIDispatch stdOut =  (IJIDispatch)JIObjectFactory.narrowObject(stdOutJIVariant.getObjectAsComObject());

// Read all from stdOut
while(!((JIVariant)stdOut.get("AtEndOfStream")).getObjectAsBoolean()){ 
    System.out.println(stdOut.callMethodA("ReadAll").getObjectAsString().getString()); 
} 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.