I have a program that I want to run from a detected USB drive (removable storage such as a USB), and this was done by creating two classes: external.java and DetectDrive.java as follows:
external.java
public class external
{
public static void main(String args[]) throws InterruptedException
{
DetectDrive d = new DetectDrive();
String DetectDrive = d.USBDetect();
BufferedWriter fileOut;
String filePath = DetectDrive;
System.out.println(filePath);
try
{
fileOut = new BufferedWriter(new FileWriter("F:\\external.bat"));
fileOut.write("cd "+ filePath +"\n");
fileOut.write("external.exe"+"\n");
fileOut.close(); //close the output stream after all output is done
Runtime rt = Runtime.getRuntime();
Process p = rt.exec("cmd /c start" +DetectDrive+ "\\external.bat");
p.waitFor();
} catch (IOException e){
e.printStackTrace();
}
}
}
DetectDrive.java
import java.io.*;
import java.util.*;
import javax.swing.filechooser.FileSystemView;
public class DetectDrive
{
public String USBDetect()
{
String driveLetter = "";
FileSystemView fsv = FileSystemView.getFileSystemView();
File[] f = File.listRoots();
for (int i = 0; i < f.length; i++)
{
String drive = f[i].getPath();
String displayName = fsv.getSystemDisplayName(f[i]);
String type = fsv.getSystemTypeDescription(f[i]);
boolean isDrive = fsv.isDrive(f[i]);
boolean isFloppy = fsv.isFloppyDrive(f[i]);
boolean canRead = f[i].canRead();
boolean canWrite = f[i].canWrite();
if (canRead && canWrite && !isFloppy && isDrive && (type.toLowerCase().contains("removable") || type.toLowerCase().contains("rimovibile")))
{
//log.info("Detected PEN Drive: " + drive + " - "+ displayName);
driveLetter = drive;
break;
}
}
/*if (driveLetter.equals(""))
{
System.out.println("Not found!");
}
else
{
System.out.println(driveLetter);
}
*/
//System.out.println(driveLetter);
return driveLetter;
}
}
The problem now is that there are no errors when I run the external.java (main). However, the output only shows the detected drive which is F:\ but it doesn’t run the specified program which is external.exe and it also mentioned that the program got terminated. Can someone please help me point out where I went wrong and what the correct codes should be like? I am new to Java.
I got the DetectDrive codes from http://www.snip2code.com/Snippet/506/Detect-USB-removable-drive-in-Java which I believe is now in maintenance.
Is it possible to change the new FileWriter("F:\external.bat") to detect the USB drive directory instead? For example letting the program detect the usb drive and automatically put in the correct directory instead of us typing the F:\ manually. I have no answer for this yet. Please help!
It seems problem is with command :
"cmd /c start" +DetectDrive+ "\\external.bat"
It should have a {space} after start:
"cmd /c start " +DetectDrive+ "\\external.bat"
Related
The following Main.java code simply tries to simulate the following linux command:
cd /dir1/dir2
./shellScript.sh
The program below works only if the executable Main.jar sits within /dir1/dir2, not outside of /dir1/dir2. How do I modify the program below so that Main.jar can sit anywhere on the file system?
public class Main {
public static String runCmdLineProcess(String commandStr){
String returnVal = "";
Runtime r = Runtime.getRuntime();
try {
Process p = r.exec(commandStr);
BufferedReader b = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = b.readLine()) != null){
returnVal += line + "\n";
}
}
catch(IOException ex){
ex.printStackTrace();
}
return returnVal;
}
public static void runProcessBuilder(String scriptPath){
String[] cmd = {scriptPath};
try {
runCmdLineProcess("cd /dir1/dir2");
Runtime.getRuntime().exec(cmd);
}
catch (IOException ex){
ex.printStackTrace();
}
}
public static void main(String[] args){
runProcessBuilder("./shellScript.sh"); // <-- works if I run from inside "/dir1/dir2".
//But if I'm outside "dir2", get an error message
// saying "Cannot run program "./shellScript.sh": error = 2, No such file or directory
}
}
You should use ProcessBuilder to launch or one of the overloads of exec. You need to specify the pathname to the script and pass the same pathname as the current directory to run the script in:
File pwd = new File("/dir1/dir2");
String shell = new File(pwd, "shellScript.sh").toString();
ProcessBuilder pb = new ProcessBuilder(shell);
// No STDERR => merge to STDOUT - or call redirectError(File)
pb.redirectErrorStream(true);
// Set CWD for the script
pb.directory(pwd);
Process p = pb.start();
// Move STDOUT to the output stream (or original code to save as String)
try(var stdo = p.getInputStream()) {
stdo.transferTo(stdout);
}
int rc = p.waitFor();
I'm doing a simple java compiler. My program is running, but if it is going to scan, it will not receive input and will freeze.
A small code from my compiler
public class ProcessBuilderMultipleCommandsExample {
static String backSlashFl = "C:\\Users\\xxA\\Desktop";
public static void main(String[] args) throws InterruptedException,
IOException {
// multiple commands
// /C Carries out the command specified by string and then terminates
ProcessBuilder pbC = new ProcessBuilder( //COMPİLE
"cmd.exe", "/c", "cd " + backSlashFl + "&& javac " + "Test" + ".java");
Process processC = pbC.start();
ProcessBuilder pb = new ProcessBuilder( //RUN
"cmd.exe", "/c", "cd " + backSlashFl + "&& java " + "Test");
Process process = pb.start();
IOThreadHandler outputHandler = new IOThreadHandler(
process.getInputStream());
outputHandler.start();
process.waitFor();
System.out.println(outputHandler.getOutput());
}
private static class IOThreadHandler extends Thread {
private InputStream inputStream;
private StringBuilder output = new StringBuilder();
IOThreadHandler(InputStream inputStream) {
this.inputStream = inputStream;
}
public void run() {
Scanner br = null;
try {
br = new Scanner(new InputStreamReader(inputStream));
String line = null;
while (br.hasNextLine()) {
line = br.nextLine();
output.append(line
+ System.getProperty("line.separator"));
}
} finally {
br.close();
}
}
public StringBuilder getOutput() {
return output;
}
}
}
I think it's working in the back, but how do I get the input part?
Here's the file I want to compile and run.
import java.awt.*;
import java.awt.event.*;
import java.util.Scanner;
public class numberScan {
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
System.out.println("Enter the number: ");
int a=scan.nextInt();
System.out.println("Number= " + a);
}
}
I'm waiting for your help.
Editted
Now when I run the GUI, the Run key is pressed. What do you think I should do?
buttonRun.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
String backSlashFl = file.getAbsolutePath().replace("\\", "\\\\");
backSlashFl = backSlashFl.replace(flName + ".java", "");
try {
execute("cmd.exe", "/c", "cd " + backSlashFl + " && java " + flName);
JOptionPane.showMessageDialog(null, "Dosya çalıştı!","Bilgilendirme",
JOptionPane.INFORMATION_MESSAGE);
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException ae) {
// TODO Auto-generated catch block
ae.printStackTrace();
} catch (Exception e2){
e2.printStackTrace();
}
}
});
When the GUI app runs, this run button remains.
There are several issues with the given code. I tried to squeeze it into a comment, but now decided to extend it to an answer:
The class that you want to compile is called numberScan, but obviously stored in a file called Test.java. A public class can only be stored in a file that has the same name as the class. Call the class NumberScan, and call the file NumberScan.java.
You are only trying to print the output that is provided by the input stream. But you are not printing the result that is provided by the error stream (so if there are errors, you will not see them!). Also, you only printed the output of the Process process (which is used for running the program). You did not print the output of the Process processC, which was used for compiling the program.
The reason of why you don't see any output is that the line
System.out.println(outputHandler.getOutput());
is executed before the process is finished. You used waitFor, but the output is filled by a different thread - namely, the IOThreadHandler. The getOutput method could only be called after the IOThreadHandler has finished, but if you want to continuously update the output, then this will not work.
It is not entirely clear what you want to achieve, but guessing from the code that you provided, your goal seems to be to create a program that
Compiles the given Java file
Executes the resulting Java program
Prints possible error messages and the output that is created by the program
Important: Allows interacting with the program, in the sense that it should be possible to send input to the System.in of the program.
The last two points are particularly hard to achive manually. You would have to set up threads for reading the input stream and the error stream. These would require some trickery to make sure that the data is read continuously while the program is executed. Additionally, you would have to set up a thread that forwards the data that the user enters to the Java program that is executed in its own process.
Fortunately, all this has become fairly trivial with Java 7: You can simply set an appropriate ProcessBuilder.Redirect for all the streams (namely, the redirect INHERIT), so that all the streams are mapped to the corresponding streams of the surrounding program.
Here is an example:
import java.io.IOException;
import java.lang.ProcessBuilder.Redirect;
import java.util.Arrays;
public class ProcessBuilderMultipleCommandsExample {
private static String path = "C:\\Users\\xxA\\Desktop";
public static void main(String[] args)
throws InterruptedException, IOException {
execute("cmd.exe", "/c", "cd " + path + " && javac " + "NumberScan" + ".java");
execute("cmd.exe", "/c", "cd " + path + " && java " + "NumberScan");
}
private static void execute(String ... commands)
throws IOException, InterruptedException
{
System.out.println("Executing "+Arrays.asList(commands));
ProcessBuilder processBuilder = new ProcessBuilder(commands);
processBuilder.redirectInput(Redirect.INHERIT);
processBuilder.redirectOutput(Redirect.INHERIT);
processBuilder.redirectError(Redirect.INHERIT);
Process process = processBuilder.start();
process.waitFor();
}
}
i have problems creating a temporary file with java through lua.
The code works if i start the jav program through the command line but if the program is started by the Lua-plugin it does not create a file.
Cases:
Command Line> java Bot !info
BotAnswer.txt will be created in Temp directory if the file already exist it will be overwritten
The file contains the correct data
Execution through Lua
ERROR: Java programm will start but BotAnswer.txt wont be created ... if file already exists nothing happens
The file is missing or contains the wrong data
If file already existed it sends the old and wrong content to the chat
I guess there are some permission errors or something like that.
It would be a huge help for me if you could tell me how to fix this.
Here are the code snippets:
located in C:\Program Files\TeamSpeak 3 Client\plugins\lua_plugin\testmodule
Lua
if targetMode == 2 then --targetMode is always 2 for this case
os.execute("java Bot " .. message) --Start java program with message as arguments (message = !info)
if message == "!info" then
folderName = os.getenv("TEMP")
fileName = "BotAnswer.txt"
filePath = io.open(folderName .. "/" .. fileName, "r")
answer = filePath:read("*all")
filePath:close()
os.remove(folderName .. "/" .. fileName)
ts3.requestSendChannelTextMsg(serverConnectionHandlerID, answer, fromID) --Send the content of BotAnswer.txt to the teamspeak Chat
end
end
Java
public class Bot {
public static void main(String[] args) {
Bot myBot = new Bot();
String command = myBot.getCommand(args);
String answer = myBot.differentiateCommand(command);
try {
myProcessor.writeAnswerToFile(answer);
} catch (Exception e) {}
}
public String getCommand(String[] args) {
if(args.length == 0) {
System.exit(0);
}
if (args[0].startsWith("!") != true) {
System.exit(0);
}
String message = args[0];
if (message.startsWith("!")) {
String[] msgArray = message.split("!");
message = msgArray[1];
}
return message;
}
public String differentiateCommand(String command) {
String answer = "";
if (command.startsWith("info")) {
answer = "Tis should be the TeamSpeak answer";
}
}
public void writeAnswerToFile(String answer)throws IOException {
String tempDir = System.getenv("TEMP");
File tempFile = new File(tempDir + "/" + "BotAnswer.txt");
tempFile.createNewFile();
FileWriter writer = new FileWriter(tempFile);
writer.write(answer);
writer.flush();
writer.close();
}
}
I have a VB script to which I need to pass username and password.
I want to run this VB script through Java code programmatically.
Is there a way that I can pass the Windows credentials to the VB script in Java programmatically?
You can have the credentials on the OS environment and read them from there:
String credentials = System.getenv().get("encrypted_credentials_or_something");
And then run your command from Java. However, Runtime.exec() won't work in some cases:
When the command is not on the System's PATH
When arguments are involved
When you want to have access to the process output
When you need to be able to kill the process
When you need to check if it terminated successfully or in error (status code != 0 - which is why you write System.exit(int) to terminate a Java application. The System.exit(1), for example, indicates abnormal termination)
That's why I created this utility class to execute external processes with arguments and everything. It works very well for me:
import java.io.*;
import java.util.*;
public class ExternalCommandHelper {
public static final void executeProcess(File directory, String command) throws Exception {
InputStreamReader in = null;
try {
//creates a ProcessBuilder with the command and its arguments
ProcessBuilder builder = new ProcessBuilder(extractCommandWithArguments(command));
//errors will be printed to the standard output
builder.redirectErrorStream(true);
//directory from where the command will be executed
builder.directory(directory);
//starts the process
Process pid = builder.start();
//gets the process output so you can print it if you want
in = new InputStreamReader(pid.getInputStream());
//simply prints the output while the process is being executed
BufferedReader reader = new BufferedReader(in);
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int status = 0;
//waits for the process to finish. Expects status 0 no error. Throws exception if the status code is anything but 0.
if ((status = pid.waitFor()) != 0) {
throw new IllegalStateException("Error executing " + command + " in " + directory.getAbsolutePath() + ". Error code: " + status);
}
} finally {
if (in != null) {
in.close();
}
}
}
//Splits the command and arguments. A bit more reliable than using String.split()
private static String[] extractCommandWithArguments(String command) {
StringTokenizer st = new StringTokenizer(command);
String[] cmdWithArgs = new String[st.countTokens()];
for (int i = 0; st.hasMoreTokens(); i++) {
cmdWithArgs[i] = st.nextToken();
}
return cmdWithArgs;
}
}
I am trying to execute .sql file from java. It runs successfully when I put exit at the end of the .sql file. Is there any possibility to run without giving exit in .sql?
Java code
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStreamReader;
public class Test {
private static String script_location = "";
private static String file_extension = ".sql";
private static ProcessBuilder processBuilder =null;
public static void main(String[] args) {
try {
//D:/Tset is the folder that contains the.sql files
File file = new File("D:/Tset");
File [] list_files= file.listFiles(new FileFilter() {
public boolean accept(File f) {
if (f.getName().toLowerCase().endsWith(file_extension))
return true;
return false;
}
});
for (int i = 0; i<list_files.length;i++){
script_location = "#" + list_files[i].getAbsolutePath();
//ORACLE
processBuilder = new ProcessBuilder
("sqlplus","user56/password", script_location); //ORACLE
//script_location = "-i" + list_files[i].getAbsolutePath();
// processBuilder =
new ProcessBuilder("sqlplus",
"-Udeep-Pdumbhead-Spc-de-deep\\sqlexpress-de_com",script_location);
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
BufferedReader in =
new BufferedReader(new InputStreamReader(process.getInputStream()));
String currentLine = null;
while ((currentLine = in.readLine()) != null) {
System.out.println(" " + currentLine);
}
}
}
catch (IOException e)
{
e.printStackTrace();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
Oracle script file:
createtable.sql
createtable.sql
create table t1(empname varchar2(20),address varchar2(20))
/
create table t2(name varchar2(20),lname varchar2(20))
/
exit;
insertvalue.sql
insert into t1 values('aaaaa','chennai')
/
insert into t2 values('bbbbb','ddddd')
/
exit;
If I don't put an exit at last it simply runs the first file only. Is there a solution to this?
In your code you run the command sqlplus in a loop so you must end every command (using exit to exit sqlplus).
If you want to call many scripts on the same sqlplus instance then maybe you can create "on the fly" a script that has commands such as:
onTheFlyAcript.sql
#createtable.sql <your params>
#insertvalue.sql <your params>
exit;
So basically you can do something like:
try {
Printwriter out = new PrintWriter(new FileWriter("D:/Test/onTheFlyScript.sql"));
for (int i = 0; i<list_files.length;i++){
script_location = "#" + list_files[i].getAbsolutePath();
out.println("START script_location");
}
out.close();
} catch (IOException e){
e.printStackTrace();
}
// note that this command is not in the loop, it's just for running the new script you've created
processBuilder = new ProcessBuilder
("sqlplus","user56/password", "D:/Test/onTheFlyAcript.sql");
This will probably have to be debuged, but the idea is that instead of executing all your scripts one by one with sqlplus, you create a new script that contains the calls to all your scripts.
Now you can remove the exit sqlplus command from all your scripts since you don't need to exit sqlplus (only in onTheFlyScript.sql)