如何从Java程序内部创建PowerShell远程会话?

时间:2017-03-28 06:04:31

标签: java powershell remoting winrm

我有以下代码连接到远程计算机并执行命令。如果我为远程计算机的每个Invoke-Command调用创建一个新会话,它正在工作。我不想在每次使用Invoke-Command时创建一个新会话,因为这不会同时扩展到数百台计算机上的数千个命令,而会话创建本身也是一个很大的开销。我需要一种方法,以便我可以在$ session powershell变量中重用相同的会话对象,以便对远程计算机进行多次Invoke-Command调用。

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

2 个答案:

答案 0 :(得分:2)

看到有很多逻辑涉及到这可以帮助你。

您的会话调用很好;但你不能直接运行这样的PS命令。您必须首先调用powershell.exe 然后您必须为相应的远程命令提供您要执行的内容。

最后你执行了你准备的命令。让我分享一个示例代码:

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

以下是如何在Java中构建命令对象,然后执行此操作:

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

要触发PS文件,您可以使用-Filepath开关。

接下来,这将帮助您执行:

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

希望它能让你出发。

答案 1 :(得分:0)

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

}