how to create a powershell remote session from inside a Java program?

半腔热情 提交于 2019-12-12 03:32:04

问题


I have the following code to connect to a remote machine and execute commands.It is working if I create a new session for each Invoke-Command call to the remote machine. I don't want to create a new session each time I use Invoke-Command as that will not scale for thousands of commands on hundreds of machines concurrently and session creation itself is a big overhead. I need a way so that I can reuse the same session object in the $session powershell variable for multiple Invoke-Command calls to the remote machines.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;

public class PowerShellSession {

private static String subModule = "PowerShellSession";
String targetIpAddress;
String username;
String password;

public static Object connectPShellLock = new Object();

public PowerShellSession() {}


public void exec(String cmd, String credentials)  { 

    String ex = "Invoke-Command -Session $session -ScriptBlock {" + cmd + "} -Computer " + targetIpAddress;

    String[] args = new String[] { "powershell", ex};
    try {
        execRemote(args);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void close() {
    String command = "Exit-PSSession";
    String[] args = new String[] { "powershell", command};
    try {
        execRemote(args);
    } catch (IOException e) {
        e.printStackTrace();
    }

}

private String getCredentials(String domain, String userName,
        String password) throws IOException {
    String creds = "$PlainPassword ='" + password
            + "'; $SecurePassword = $PlainPassword | ConvertTo-SecureString -AsPlainText -Force;"
            + "$mycred = new-object -typename System.Management.Automation.PSCredential('" + userName + "', $SecurePassword);";
    creds += "$session = New-PSSession -ComputerName " + domain + " -Credential $mycred;";

    String[] args = new String[] { "powershell", creds};
    execRemote(args);
    return creds;
}

private void execRemote(String[] arguments) throws IOException {
    ProcessBuilder builder = new ProcessBuilder(arguments);
    builder.redirectErrorStream(true);
    Process process = builder.start();
    doProcessIO(process);
}

// Do the IO for a passed process
private void doProcessIO(Process p) throws IOException {
    p.getOutputStream().close();
    String line;
    System.out.println("Output:");
    BufferedReader stdout = new BufferedReader(new InputStreamReader(
            p.getInputStream()));
    while ((line = stdout.readLine()) != null) {
        System.out.println(line);
    }
    stdout.close();
    System.out.println("Error:");
    BufferedReader stderr = new BufferedReader(new InputStreamReader(
            p.getErrorStream()));
    while ((line = stderr.readLine()) != null) {
        System.out.println(line);
    }
    stderr.close();
//      System.out.println("Done");
}

public static void main(String[] args) throws IOException {
    PowerShellSession psSession = new PowerShellSession();
    String credentials = psSession.getCredentials("9.120.241.195", "username", "password");
    psSession.targetIpAddress = "9.120.241.195";
    if(!credentials.equals("")) {
        Scanner input = new Scanner(System.in);
        while(true) {
            System.out.print("PS C:\\Windows\\system32> ");
            String cmd = input.nextLine();
            if(cmd.equals("q") || cmd.equals("e") || cmd.equals("quit") || cmd.equals("exit")) break;
            psSession.username = "username";
            psSession.password = "password";
            psSession.exec(cmd, "");
        }
        System.out.println("Finished PowerShell remote session.");
        input.close();
    }
    psSession.close();
}
}

回答1:


See there are lot of logics involves in this which can help you.

Your session invoking is fine; But you cannot directly run a PS command like that. You have to invoke the powershell.exe first then you have to give the respective remote commands what you want to execute.

Finally you have execute the command you will prepare. Let me share you a sample code:

public String executeScript(String psFileName, Systems system) throws NMAException {

        Runtime runtime = Runtime.getRuntime();
        String filePath = ApplicationProperties.getPropertyValue("powershell.scripts.location");
        String command;

        switch (psFileName) {
            case "TerminalServersSystemInfo.ps1":
                command = POWERSHELL + filePath + psFileName + " " + system.getPassword() + " " + system.getUserName()
                        + " " + system.getSystemName();
                break;
            case "SQLServerInfo.ps1":
                command = POWERSHELL + filePath + psFileName + " " + system.getSystemName() + " "
                        + system.getUserName() + " " + system.getPassword();
                break;
            case "MyPS.ps1":

            {
                command = POWERSHELL + filePath + psFileName + " " + system.getSystemName() + " "
                        + system.getUserName()
                        + " " + system.getPassword() + " " + system.getDatabaseName();
                break;
            }

            default:
                throw new NMAException("not available");
        }

Here is how you should form the command object in Java and then you should execute this:

powershell -ExecutionPolicy Bypass -NoLogo -NoProfile -Command {Invoke-command ......}

For triggering a PS file you can use the -Filepath switch.

Next this will help you in executing that:

proc = runtime.exec(command);
            proc.getOutputStream().close();
            InputStream is = proc.getInputStream();
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader reader = new BufferedReader(isr);
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            reader.close();
            proc.getOutputStream().close();
            LOGGER.info("Command: " + command);
            LOGGER.info("Result:" + sb.toString());
            return sb.toString();

Hope it gives you a set off.




回答2:


public class PowerShellSession {
    private static String subModule = "PowerShellSession";
    String targetIpAddress;
    String username;
    String password;

    public static Object connectPShellLock = new Object();

    public PowerShellSession() {}


    public void exec(String cmd, String credentials)  { 

        String ex = credentials +" Invoke-Command -ScriptBlock {" + cmd + "} -ComputerName " + targetIpAddress +" -Credential $mycred";

        String[] args = new String[] { "powershell", ex};
        try {
            execRemote(args);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void close() {
        String command = "Exit-PSSession";
        String[] args = new String[] { "powershell", command};
        try {
            execRemote(args);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private String getCredentials(String domain, String userName,
            String password) throws IOException {
        String creds = "$Username = '"+userName+"';$PlainPassword ='" + password
                + "'; $SecurePassword = ConvertTo-SecureString -AsPlainText $PlainPassword -Force;"
                + "$mycred = New-Object System.Management.Automation.PSCredential -ArgumentList $Username, $SecurePassword;";
        //creds += "$session = New-PSSession -ComputerName " + domain + " -Credential $mycred;";

        String[] args = new String[] { "powershell", creds};
        execRemote(args);
        return creds;
    }

    private void execRemote(String[] arguments) throws IOException {
        ProcessBuilder builder = new ProcessBuilder(arguments);
        builder.redirectErrorStream(true);
        Process process = builder.start();
        doProcessIO(process);
    }

    // Do the IO for a passed process
    private void doProcessIO(Process p) throws IOException {
        p.getOutputStream().close();
        String line;
        System.out.println("Output:");
        BufferedReader stdout = new BufferedReader(new InputStreamReader(
                p.getInputStream()));
        while ((line = stdout.readLine()) != null) {
            System.out.println(line);
        }
        stdout.close();
        System.out.println("Error:");
        BufferedReader stderr = new BufferedReader(new InputStreamReader(
                p.getErrorStream()));
        while ((line = stderr.readLine()) != null) {
            System.out.println(line);
        }
        stderr.close();
        System.out.println("Done");
    }

    public static void main(String[] args) throws IOException {
        PropertiesFileReader propReader = new PropertiesFileReader(System.getProperty("user.dir")+"/cred.properties");

        String user = propReader.getPropertyData("user");
        String pass = propReader.getPropertyData("pass");
        String ip_add = propReader.getPropertyData("ip");

        PowerShellSession psSession = new PowerShellSession();
        String credentials = psSession.getCredentials(ip_add, user, pass);
        psSession.targetIpAddress = ip_add;//;



        String cmdd = propReader.getPropertyData("command");//"Get-Culture";
        if(!credentials.equals("")) {


            psSession.exec(cmdd, credentials);

            System.out.println("Finished PowerShell remote session.");

        }
        psSession.close();
    }

}


来源:https://stackoverflow.com/questions/43061714/how-to-create-a-powershell-remote-session-from-inside-a-java-program

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!