在某些場景下,需要在Java程序中使用Powershell進行終端交互,這種情況下當然可以直接使用自帶的Runtime來完成:
Runtime.getRuntime().exec("powershell.exe Get-Item");
但是這種只適合需要單條指令的情況,而存在多條指令時,無法保證前后指令的關聯性。這里介紹一個第三方的類庫:jPowershell
Maven中引入如下依賴:
<dependency>
<groupId>com.profesorfalken</groupId>
<artifactId>jPowerShell</artifactId>
<version>3.1.1</version>
</dependency>
接下來,在程序中就可以通過如下方式獲取到一個Powershell的實例:
PowerShell session = PowerShell.openSession();
PowerShell對象提供了如下的基礎方法:
configuration(Map<String,String> arg0) |
指定配置對象 | void | 修改默認配置時使用 |
openSession() |
PowerShell | 啟動一個PowerShell會話 | |
openSession(String arg0) |
指定PowerShell終端的路徑 | PowerShell | 啟動一個PowerShell會話 |
executeCommand(String arg0) |
Powershell指令 | PowerShellResponse | 執行一條PowerShell指令 |
executeSingleCommand() |
Powershell指令 | PowerShellResponse | 執行單一PowerShell指令(無會話模式) |
executeCommandAndChain(String arg0,PowerShellResponseHandler.. arg1) |
PowerShell指令,Response處理器 | PowerShell | 執行一條PowerShell指令並對其Response進行處理 |
handleResponse(PowerShellResponseHandler arg0,PowerShellResponse arg1) |
Response處理器,Response | void | 使用指定Response處理器處理響應 |
isLastCommandInError() |
boolean | 最后一條指令是否出錯 | |
executeScript(String arg0) |
腳本路徑 | PowerShellResponse | 執行指定的腳本 |
| executeScript(String arg0, String arg1) | 腳本路徑,執行參數 | PowerShellResponse | 傳入參數執行指定腳本 |
| executeScript(BufferedReader arg0) | 腳本緩沖對象 | PowerShellResponse | 從緩沖對象中執行腳本 |
| executeScript(BufferedReader arg0, String arg1) | 腳本緩沖對象,執行參數 | PowerShellResponse | 傳入參數執行緩沖對象中的腳本 |
| close() | void | 關閉會話 | |
| closeAndWait(Future<String> arg0) | 異步對象列表 | boolean | 等待異步對象列表中全部Task完成后關閉會話 |
| checkState() | void | 檢查當前會話狀態 |
獲取到的session對象是一個新的Powershell會話實例,可以通過下述方式來執行指令:
String readContext = "Get-Content D:\\1.sql";
session.executeCommand("$user = \""+username+"\"");
session.executeCommand("$password = ConvertTo-SecureString \"" +password + "\" -AsPlainText -Force");
session.executeCommand("$credential = New-Object System.Management.Automation.PSCredential($user,$password)");
response = session.executeCommand("Invoke-Command -ComputerName " + server + " -Credential $credential -ScriptBlock {" + readContext + "}");
System.out.println(response.getCommandOutput().length());
上述代碼中,首先定義了兩個shell變量,$user和$password,而后通過調用System.Management.Automation.PSCredential構造了一個$credential對象,再將其作為-Credential的值傳入下一條指令中,完成遠程Invoke-Command進行文件內容長度的讀取。
每一條session.executeCommand()都會返回一個PowerShellResponse對象,可以通過調用這個對象的getCommandOutput()方法來獲取命令輸出。注意看日志最后的數字:
public class PowerShell implements AutoCloseable {
private static final Logger logger = Logger.getLogger(PowerShell.class.getName());
private Process p;
private long pid = -1L;
private PrintWriter commandWriter;
private boolean closed = false;
private ExecutorService threadpool;
private static final String DEFAULT_WIN_EXECUTABLE = "powershell.exe";
private static final String DEFAULT_LINUX_EXECUTABLE = "powershell";
private int waitPause = 5;
private long maxWait = 10000L;
private File tempFolder = null;
private boolean scriptMode = false;
public static final String END_SCRIPT_STRING = "--END-JPOWERSHELL-SCRIPT--";
private PowerShell() {
}
public PowerShell configuration(Map<String, String> config) {
try {
this.waitPause = Integer.valueOf(config != null && config.get("waitPause") != null ? (String)config.get("waitPause") : PowerShellConfig.getConfig().getProperty("waitPause"));
this.maxWait = Long.valueOf(config != null && config.get("maxWait") != null ? (String)config.get("maxWait") : PowerShellConfig.getConfig().getProperty("maxWait"));
this.tempFolder = config != null && config.get("tempFolder") != null ? this.getTempFolder((String)config.get("tempFolder")) : this.getTempFolder(PowerShellConfig.getConfig().getProperty("tempFolder"));
} catch (NumberFormatException var3) {
logger.log(Level.SEVERE, "Could not read configuration. Using default values.", var3);
}
return this;
}
}
Powershell提供了一個configuration()方法,這個方法接受一個Map類型的配置參數,並將內容解析后代替默認參數。我們主要關注的是maxWait的值。通過成員定義可以看出,默認的maxWait的值就是10000毫秒,也就是10秒。因此,可以通過如下代碼來使其支持更長時間指令的調用:
PowerShell session = PowerShell.openSession();
Map<String,String> configMap = new HashMap<>();
configMap.put("maxWait","600000");
session.configuration(configMap);
這樣就把指令的最長等待時間設置為了600秒。

