• Post Reply Bookmark Topic Watch Topic
  • New Topic

Running a .bat file with Java code  RSS feed

 
Michael Scott
Ranch Hand
Posts: 57
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm trying to run a .bat file with Java code. The following code does not run the .bat file even though the variable 'batCommand' contains the name of a valid bat file (test.bat). This was verified by writing the variable to a log file.
_____________________________________
String batCommand = bufferName.toString();
LogAccessor.getLogger().logAction(batCommand); // e.g. returns test.bat
Process child = Runtime.getRuntime().exec(batCommand);
_____________________________________


However, when the variable 'batCommand' is replaced with the explicit name of the .bat file as follows, the code does run the .bat file.
______________________________________
Process child = Runtime.getRuntime().exec("test.bat");
______________________________________


Under both scenarios, the .bat file has full permissions and it runs in a command prompt. Is there any reason why the .bat file might not execute when it's referenced as a variable rather than explicitly?

Thanks.
 
Edwin Dalorzo
Ranch Hand
Posts: 961
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you test batCommand.equals("test.bat"), does it yield true?
 
Michael Scott
Ranch Hand
Posts: 57
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
As suggested, I added the following code (in italics).
___________________________________________
String batCommand = bufferName.toString();
LogAccessor.getLogger().logAction(batCommand); // e.g. returns test.bat

if (batCommand.equals("test.bat")) {
LogAccessor.getLogger().logAction("True");
} else {
LogAccessor.getLogger().logAction("False");
}


Process child = Runtime.getRuntime().exec(batCommand);
________________________________________________

The added code returned 'True'. Incredibly, the variable 'batCommand' was then correctly recognized as having a value of 'test.bat' and the .bat file ran - simply, by adding the code in italics. This was so unexpected, I added and removed the code in italics a couple of times, and each time the result was the same - if the code in italics exists, the variable 'batCommand' is recognized as having a value of 'test.bat' and the .bat file runs. I then replaced the above code in italics with some random nonsense code as follows and the results were the same:
____________________________________________
if ("cat".equals("dog")) {
LogAccessor.getLogger().logAction("True");
} else {
LogAccessor.getLogger().logAction("False");
}

_____________________________________________

It's almost as if any code needs to exist between the following two lines in order for the second line to run properly.
_____________________________________________
String batCommand = batPathBufferB.toString();
Process batChild = Runtime.getRuntime().exec(batCommand);
_______________________________________________

I'm still quite a novice at Java, but I've never seen anything like this in all my years of programming. I'd appreciate any suggestions on why the results described here might occur.

Thanks.
 
Henry Wong
author
Sheriff
Posts: 23295
125
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It's almost as if any code needs to exist between the following two lines in order for the second line to run properly.


I find this really hard to believe. Could you post a working test program? It's hard to tell with code snippets.

Thanks,
Henry
 
John Kelty
Ranch Hand
Posts: 33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Maybe it's a timing problem or race condition with the .bat file? That is, maybe your Java program and the .bat file interfere with each other somehow. So perhaps the extra code you put in is really just required to subtly alter the timing of when the .bat is launched relative to when the Java program is running.

I'm curious to know exactly what happens when it fails, and if there is any tie between the two jobs. What if you put in a tiny sleep or Thread yield statement and get the same results?
 
William Brogden
Author and all-around good cowpoke
Rancher
Posts: 13078
6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Also - are you consuming the standard out and standard err output streams created by the bat file execution? Failure to consume these streams can cause weird results and mysterious hangs.
Bill
 
Michael Scott
Ranch Hand
Posts: 57
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Below is more of the code which shows how the .bat file is being used. The code does the following:

1.) Creates a .bat file.
2.) Adds contents to the .bat file.
3.) Creates a 'chmod' command to grant full permissions to the .bat file.
4.) Runs the 'chmod'.
5.) Creates the command to run the .bat file.
6.) Runs the .bat file.


The contents of the .bat file is as follows. (The test.fo and test.pdf file names are actually unique).

cd /baseDirectory;./run.sh -d /sourceDirectory/test.fo -o /targetDirectory/test.pdf


The .bat file should do the following:

A.) Change to a directory
B.) Run a shell script that reads an input .fo file and creates an output .pdf file


There are two related problems - first, if a block of code is missing prior to Step 6, this results in no .pdf file being created by the .bat file. Second, if a block of code exists prior to Step 6, a .pdf is created, but it's not recognized by a line of code after the try-catch block below which attempts to create an attachment with the .pdf. (Only .pdf's created from prior runs of the code can be used to create attachments.)

I'd appreciate any ideas of this. Thanks.
---------------------------------------------------------------------------

try {

// create a .bat file
StringBuffer batFileNameBuffer = new StringBuffer(delRef);
batFileNameBuffer.append
(".bat");
String batFileName = batFileNameBuffer.toString();

File batFile = new File (batFileName);

// Create a file if it does not exist;
boolean batSuccess = batFile.createNewFile();
if (batSuccess) {
// File did not exist and was created.
} else {
// File already exists.
}

// add contents to the bat file

StringBuffer batCommandBufferA = new StringBuffer
("cd /opt/ANTHaxfov3;./run.sh -d /notesdata/");
batCommandBufferA.append(delRef);
String batCommandStrA = batCommandBufferA.toString();
StringBuffer batCommandBufferB = new StringBuffer(batCommandStrA);
batCommandBufferB.append(".fo -o /opt/ANTHaxfov3/samples/java/");
String batCommandStrB = batCommandBufferB.toString();
StringBuffer batCommandBufferC = new StringBuffer(batCommandStrB);
batCommandBufferC.append(delRef);
String batCommandStrC = batCommandBufferC.toString();
StringBuffer batCommandBufferD = new StringBuffer(batCommandStrC);
batCommandBufferD.append(".pdf");
String batCommandStrD = batCommandBufferD.toString();

Writer batOut = new BufferedWriter(new OutputStreamWriter(new
FileOutputStream(batFileName),"UTF8"));
batOut.write(batCommandStrD);
batOut.close();

// create the chmod to grant full permissions to the .bat file
StringBuffer chmodBufferA = new StringBuffer("chmod guo+rwx ");
chmodBufferA.append(delRef);
String chmodStrA = chmodBufferA.toString();
StringBuffer chmodBufferB = new StringBuffer(chmodStrA);
chmodBufferB.append(".bat");
String chmodCommand = chmodBufferB.toString();

// run the chmod command
Process chmodChild = Runtime.getRuntime().exec(chmodCommand);

// create the command to run the .bat file

StringBuffer batPathBufferA = new StringBuffer();
batPathBufferA.append(delRef);
String batPathStrA = batPathBufferA.toString();
StringBuffer batPathBufferB = new StringBuffer(batPathStrA);
batPathBufferB.append(".bat");
String batCommand = batPathBufferB.toString();

// the following block of code is random, but required in order for
// the .bat command to run as intended

if ("cat".equals("dog")) {
LogAccessor.getLogger().logAction("Equal");
} else {
LogAccessor.getLogger().logAction("Not equal");
}

// run the bat command
Process batChild = Runtime.getRuntime().exec(batCommand);

} catch (IOException e) {
}
 
Ernest Friedman-Hill
author and iconoclast
Sheriff
Posts: 24217
38
Chrome Eclipse IDE Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, there you go -- it's the race condition, as previously explained. The mysteriously needed extra code just provides a small delay, long enough for the chmod command to actually execute. A process launched by Runtime.exec() run asynchronously -- i.e., the program keeps going while the new process starts up in parallel. Without the extra code, the second Runtime.exec() begins before the chmod has executed, and then it fails to run the script.

I would expect that sending data to the logger is the key, as it probably provides an invitation for the OS to context-switch and let the other processes have a little time to run.

Note that until you showed us this code, everybody most likely thought you were talking about Windows, not UNIX -- we don't call 'em "*.bat" files on UNIX, but rather "shell scripts." Therefore, nobody was thinking about executability.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!