Invoke Powershell scripts from Java - java

I want to invoke my powershell script from java. Can it be done. I tried with the following code, but the stream is not closing.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class TestPowershell {
public static void main(String[] args) throws IOException
{
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("powershell C:\\testscript.ps1");
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr);
String line;
while ((line = reader.readLine()) != null)
{
System.out.println(line);
}
reader.close();
proc.getOutputStream().close();
}
}
Does java invoke a powershell script which performs create remote session and execute cmdlets?
Do we have support to invoke powershell scripts in java?
Anyone could you please help on this.
Awaiting for your responses.
Thanks,
rammj

After starting the process ( runtime.exec() ), add a line to close the input stream of the process ( which JAVA calls output stream!!):
proc.getOutputStream().close();

Now you can do it easily with jPowerShell
powerShell = PowerShell.openSession();
//Print results
System.out.println(powerShell.executeScript("\"C:\\testscript.ps1\"").getCommandOutput());
powerShell.close();

Yes we can create remote session and execute cmdlets using powershell script.
Save the following Power shell script to testscript.ps1
#Constant Variables
$Office365AdminUsername="YOUR_USERNAME"
$Office365AdminPassword="TOUR_PASSWORD"
#Main
Function Main {
#Remove all existing Powershell sessions
Get-PSSession | Remove-PSSession
#Encrypt password for transmission to Office365
$SecureOffice365Password = ConvertTo-SecureString -AsPlainText $Office365AdminPassword -Force
#Build credentials object
$Office365Credentials = New-Object System.Management.Automation.PSCredential $Office365AdminUsername, $SecureOffice365Password
Write-Host : "Credentials object created"
#Create remote Powershell session
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell -Credential $Office365credentials -Authentication Basic –AllowRedirection
Write-Host : "Remote session established"
#Check for errors
if ($Session -eq $null){
Write-Host : "Invalid creditials"
}else{
Write-Host : "Login success"
#Import the session
Import-PSSession $Session
}
#To check folder size
Get-MailboxFolderStatistics "YOUR_USER_NAME" | Select Identity, FolderAndSubfolderSize
exit
}
# Start script
. Main
Java Code :
try {
String command = "powershell.exe \"C:\\testscript.ps1\"";
ExecuteWatchdog watchdog = new ExecuteWatchdog(20000);
Process powerShellProcess = Runtime.getRuntime().exec(command);
if (watchdog != null) {
watchdog.start(powerShellProcess);
}
BufferedReader stdInput = new BufferedReader(new InputStreamReader(powerShellProcess.getInputStream()));
String line;
System.out.println("Output :");
while ((line = stdInput.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
If you do not get output, try this: powerShellProcess.getErrorStream() instead powerShellProcess.getInputStream(). It will show the errors.

Related

Strange behavior while running remote powershell execution from Java

I have a Windows server with WSUS and I am trying to activate some powershell script sitting on that machine.
First of all, the script works when I am trying to activate it via power shell admin shell.
The script looks like this :
Enable-PSRemoting
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "*" -Force
$secpasswd = ConvertTo-SecureString "p#`$`$w0rd" -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential ("1.1.2.3\administrator", $secpasswd)
$s = New-PSSession -ComputerName 1.1.2.3 -Credential $creds
Invoke-Command -Session $s -Scriptblock {Get-Hotfix}
I am using 2 different approach via Java :
public static void run2() throws IOException {
Runtime runtime = Runtime.getRuntime();
Process proc = new ProcessBuilder()
.inheritIO()
.command("powershell", "invoke-command",
"-Computer", "1.1.2.3",
"-Scriptblock" ,"{&C:\\install-patch-ocomputer.ps1}").start();
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr);
String line;
while ((line = reader.readLine()) != null)
{
System.out.println(line);
}
reader.close();
proc.getOutputStream().close();
}
public static void run6() throws IOException {
Runtime runtime = Runtime.getRuntime();
BufferedReader reader = null;
Process proc = runtime.exec("powershell Invoke-Command -Computer 1.1.2.3 -Scriptblock {&C:\\install-patch-computer.ps1}");
try {
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
reader = new BufferedReader(isr);
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e){
e.printStackTrace();
} finally {
reader.close();
proc.getOutputStream().close();
}
}
When I am running run2 method I get :
[1.1.2.3] Connecting to remote server 1.1.2.3 failed with the following error message : The WinRM client
cannot process the request. Default authentication may be used with an IP address under the following conditions: the
transport is HTTPS or the destination is in the TrustedHosts list, and explicit credentials are provided. Use
winrm.cmd to configure TrustedHosts. Note that computers in the TrustedHosts list might not be authenticated. For more
information on how to set TrustedHosts run the following command: winrm help config. For more information, see the
When running run6 :
No error, but no output from script as well...
Please help !!!!

Executing Vmware PowerShell Commands in Java Program

I wrote a Java program which executes a PowerShell Command. Here is my code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class PowerShellCommand {
public static void main(String[] args) throws IOException {
String command = "powershell.exe your command";
// Getting the version
String command = "powershell.exe $PSVersionTable.PSVersion";
// Executing the command
Process powerShellProcess = Runtime.getRuntime().exec(command);
// Getting the results
powerShellProcess.getOutputStream().close();
String line;
System.out.println("Standard Output:");
BufferedReader stdout = new BufferedReader(new InputStreamReader(
powerShellProcess.getInputStream()));
while ((line = stdout.readLine()) != null) {
System.out.println(line);
}
stdout.close();
System.out.println("Standard Error:");
BufferedReader stderr = new BufferedReader(new InputStreamReader(
powerShellProcess.getErrorStream()));
while ((line = stderr.readLine()) != null) {
System.out.println(line);
}
stderr.close();
System.out.println("Done");
}
}
What I want to do is: instead of executing a command in a local PowerShell I want to make the code execute a command in the Windows Server PowerShell which is running on VMware? How should I modify the code to do so?
Have PowerShell invoke the command on the remote host:
String server = "remotehost";
String command = "powershell.exe -Command \"&{Invoke-Command -Computer " +
server + " -ScriptBlock {$PSVersionTable.PSVersion}}\"";
The remote host needs to have PSRemoting enabled for this to work.

Executing grep command on Linux from Java always returning null

I am executing grep command from java on a linux file. Its always returning null for the following code.
Process p;
String matchStr="testmatch";
String output = null;
try {
String command = "grep \""+matchStr+"\" "+ filename;
System.out.println("Running command: " + command);
p = Runtime.getRuntime().exec(command);
System.out.println("***********************************");
System.out.println("***********************************");
System.out.println("***********************************");
p.waitFor();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
while (br.readLine() != null) {
System.out.println("in while loop");
System.out.println("in while loop");
System.out.println("in while loop");
System.out.println(output);
System.out.println("***********************************");
System.out.println("***********************************");
System.out.println("***********************************");
System.out.println("***********************************");
// Process your output here
}
System.out.println("exit: " + p.exitValue());
p.destroy();
} catch (Exception e) {
e.printStackTrace();
}
If i grep it directly it shows output but from java it never gets into while loop.
Please suggest whats wrong here.
The problem is that you do not write anything to output so it stays null. I guess you have to rewrite your while loop like this
while ((output = br.readLine()) != null) {
// Process your output here
}
Take a note that this syntax is discouraged by most style check due to it's abmiguity
Also it's a good idea to place p.waitFor() after while loop so grep would not hang on flushig std(err|out).
UPDATE
Also it is a good idea to use ProcessBuilder (available since java-7) instead of Runtime.getRuntime().exec(...) because you will have more control over the process i.e
final ProcessBuilder builder = new ProcessBuilder();
builder.command("grep", matchStr, filename);
// redirect stderr to stdout
builder.redirectErrorStream(true);
final Process process = builder.start();
BufferedReader br = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String output = null;
while ((output = br.readLine()) != null) {
System.out.println(output);
// Process your output here
}
process.waitFor();
After turning your code into a https://stackoverflow.com/help/mcve it works for me.
Here the file does not exist:
robert#habanero:~$ rm /home/robert/greptest.txt
robert#habanero:~$ javac GrepTest.java && java GrepTest
Running command: grep test /home/robert/greptest.txt
exit: 2
Now the file does exist but does not contain the text to be found:
robert#habanero:~$ echo not found > /home/robert/greptest.txt
robert#habanero:~$ javac GrepTest.java && java GrepTest
Running command: grep test /home/robert/greptest.txt
exit: 1
Now the file exists and contains the text:
robert#habanero:~$ echo test this > /home/robert/greptest.txt
robert#habanero:~$ javac GrepTest.java && java GrepTest
Running command: grep test /home/robert/greptest.txt
test this
exit: 0
Here is the code:
import java.io.*;
public class GrepTest {
public static void main(String[] args) throws Exception {
String command = "grep test /home/robert/greptest.txt";
System.out.println("Running command: " + command);
Process p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String output;
while ((output = br.readLine()) != null) {
System.out.println(output);
}
System.out.println("exit: " + p.exitValue());
p.destroy();
}
}
I was recently struggling with a similar issue, and I believe I the solution I found is an answer also to your problem (though your question is a bit malformed as others have pointed out).
The issue pertrains to the quote marks around your search string,
\""+matchStr+"\"
The java exec command will literally deliver these to the grep command, and instead of searching for matchStr, grep will be looking for "matchStr", and the results will not be what you are expecting.
This applies also in case one is executing the command as an array like
final Process process = Runtime.getRuntime().exec(new String[] { "grep", "-C1000", searchString, fileName } );
Pass the plain searchString without including quotation marks into the string.

Executing PowerShell Commands in Java Program

I have a PowerShell Command which I need to execute using Java program. Can somebody guide me how to do this?
My command is Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName, DisplayVersion, Publisher, InstallDate |
Format-Table –AutoSize
You should write a java program like this, here is a sample based on Nirman's Tech Blog, the basic idea is to execute the command calling the PowerShell process like this:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class PowerShellCommand {
public static void main(String[] args) throws IOException {
//String command = "powershell.exe your command";
//Getting the version
String command = "powershell.exe $PSVersionTable.PSVersion";
// Executing the command
Process powerShellProcess = Runtime.getRuntime().exec(command);
// Getting the results
powerShellProcess.getOutputStream().close();
String line;
System.out.println("Standard Output:");
BufferedReader stdout = new BufferedReader(new InputStreamReader(
powerShellProcess.getInputStream()));
while ((line = stdout.readLine()) != null) {
System.out.println(line);
}
stdout.close();
System.out.println("Standard Error:");
BufferedReader stderr = new BufferedReader(new InputStreamReader(
powerShellProcess.getErrorStream()));
while ((line = stderr.readLine()) != null) {
System.out.println(line);
}
stderr.close();
System.out.println("Done");
}
}
In order to execute a powershell script
String command = "powershell.exe \"C:\\Pathtofile\\script.ps\" ";
No need of reinvent the wheel. Now you can just use jPowerShell
String command = "Get-ItemProperty " +
"HKLM:\\Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\* " +
"| Select-Object DisplayName, DisplayVersion, Publisher, InstallDate " +
"| Format-Table –AutoSize";
System.out.println(PowerShell.executeSingleCommand(command).getCommandOutput());
you can try to calle the powershell.exe with some commands like :
String[] commandList = {"powershell.exe", "-Command", "dir"};
ProcessBuilder pb = new ProcessBuilder(commandList);
Process p = pb.start();
You can use -ExecutionPolicy RemoteSigned in the command.
String cmd = "cmd /c powershell -ExecutionPolicy RemoteSigned -noprofile -noninteractive C:\Users\File.ps1

How to supply sudo with root password from Java?

I'm trying to write a small Java app that will overwrite my /etc/resolv.conf file (I'm on Ubuntu 12.04). To do so, I need to supply my root password:
myUser#myMachine:~$ sudo vim /etc/resolv.conf
[sudo] password for myUser: *****
So the process for doing this has three steps:
Type sudo vim /etc/resolv.conf at terminal
Terminal asks me to type my root password
I enter the password and press [Enter]
From everything I've researched, I could use the following for performing step #1 above:
try {
String installTrickledCmd = "sudo vim /etc/resolv.conf";
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec(installTrickledCmd);
}
catch(Throwable throwable) {
throw new RuntimeException(throwable);
}
But when this executes, the shell will want to prompt my Java process for the password. I'm not sure how to wait for this (step #2 above) and then to supply my password back to the shell (step #3 above). Thanks in advance.
Have you tried with -S ?
$echo mypassword | sudo -S vim /etc/resolv.conf
From man:
The -S (stdin) option causes sudo to read the password from the standard input
instead of the terminal device. The password must be followed by a newline
character.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
public class Test1 {
public static void main(String[] args) throws Exception {
String[] cmd = {"sudo","-S", "ls"};
System.out.println(runSudoCommand(cmd));
}
private static int runSudoCommand(String[] command) throws Exception {
Runtime runtime =Runtime.getRuntime();
Process process = runtime.exec(command);
OutputStream os = process.getOutputStream();
os.write("harekrishna\n".getBytes());
os.flush();
os.close();
process.waitFor();
String output = readFile(process.getInputStream());
if (output != null && !output.isEmpty()) {
System.out.println(output);
}
String error = readFile(process.getErrorStream());
if (error != null && !error.isEmpty()) {
System.out.println(error);
}
return process.exitValue();
}
private static String readFile(InputStream inputStream) throws Exception {
if (inputStream == null) {
return "";
}
StringBuilder sb = new StringBuilder();
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line = bufferedReader.readLine();
while (line != null) {
sb.append(line);
line = bufferedReader.readLine();
}
return sb.toString();
} finally {
if (bufferedReader != null) {
bufferedReader.close();
}
}
}
}
Inspired from Viggiano answer.

Categories