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
Vladlen Gladis
  • 1,699
  • 5
  • 19
  • 41
  • Check this link: https://social.technet.microsoft.com/Forums/office/en-US/d32537bd-0aef-440e-8760-6b3085390c37/executing-powershell-script-via-java?forum=winserverpowershell At the very end of this there is a working example including error handling. – Martin Apr 28 '16 at 08: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 – Vladlen Gladis Apr 28 '16 at 08:10
  • Possibly related: https://serverfault.com/questions/638659/managing-windows-powershell-from-linux-terminal – Ryan Bemrose Jul 19 '16 at 16:25
  • https://github.com/xebialabs/overthere - powers some of the "CI-CD" tools.. OT: Your requirement could be addressed via tools like https://xebialabs.com/products/xl-deploy/ or rundeck. – Jayan Jul 22 '16 at 03: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. – Dominic Jul 25 '16 at 21:56
  • You can call Invoke-command in java with Process Builder refer https://stackoverflow.com/questions/40351357/running-powershell-script-remotely-through-java – user2025527 Nov 30 '18 at 06:27
  • Refer https://stackoverflow.com/questions/40351357/running-powershell-script-remotely-through-java – user2025527 Nov 30 '18 at 06:28

5 Answers5

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();
}
digz6666
  • 1,798
  • 1
  • 27
  • 37
  • 2
    I don't see any remote execution of script in your answer. Question is asking for remote execution of script. – Erlan Aug 15 '18 at 10:06
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.

Hash
  • 4,647
  • 5
  • 21
  • 39
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();
Aboud Zakaria
  • 567
  • 9
  • 25
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!'
darthfather
  • 377
  • 3
  • 12
0

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()); 
} 
Community
  • 1
  • 1
Alexander Petrov
  • 9,204
  • 31
  • 70