简体   繁体   中英

Remote Powershell scripts via Java

May you know some APIs for Java to invoke remote PowerShell scripts?

From this API I need things like:

  • Log into Windows machine.
  • Execute PowerShell script
  • Get result of script execution

Or exists another methods to do it? Thanks

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

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.

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

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!'

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM