Link to home
Start Free TrialLog in
Avatar of mark_667
mark_667

asked on

Executing a batch file from process exec

I have a thread which needs to read the output of a batch file in the run() but I'm having trouble executing the batch file. The batch file merely issues a javac and java command to execute a class file from another project (which I don't have the source for) and works fine when executed manually. However, when I try executing the batch file through process exec, it gives:

Microsoft Windows [Version 5.2.3790]
(C) Copyright 1985-2003 Microsoft Corp.
Exception in thread "main"
java.lang.NoClassDefFoundError

I tried putting another process immediately before p
Process o = Runtime.getRuntime().exec("java -classpath C:\\full-path-to-batch-file here");
but it didn't make any difference.

It works when executed from the Windows run dialog but if it is executed from a command line from the same directory as the java source files we get the same error. If placed in the same directory as the source it still gives the error. Is it, then, not a fault in my program but something to do with the Java classpath? If so how can I compensate for it? If I need to execute the class file directly can I do so without using JNI?


      public void run()
      {
            BufferedReader stdInput;
            OutputStream stdOut;
            BufferedReader stdError;
            String strBatchPath="full-path-to-executable-bat-here";
            String strBatchOutput="";
            String strBatchErrorOutput="";
            Process p;
            

            try
            {
                  p = Runtime.getRuntime().exec(strBatchPath);
                  
                  while(isInterrupted==false)
                  {
                        try
                        {
                              Thread.sleep(iThreadSleepTime);
                        }
                        catch(InterruptedException e){}
                        
                    try
                    {
                        stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
                        stdOut = p.getOutputStream();
                        stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
            
                        // read the output from the batch file

                              strBatchOutput = stdInput.readLine();
                              
                              if((strBatchOutput==null)||(strBatchOutput.length()<1)) {}
                              else
                              {
                                    //do something here
                              }
                                    

                            if((strBatchErrorOutput==null)||(strBatchErrorOutput.length()>1))
                            {
                                  //if we cannot get started output an error
                                  //TODO: Figure out what keeps causing this
                                  if(strBatchErrorOutput.startsWith("java.lang.NoClassDefFoundError"))
                                  {
                                        JOptionPane.showMessageDialog(g_parentFrame, "An error occured" +
                                                    " while attempting to run the Batch:\n"+
                                              strBatchErrorOutput+"\n Please check the batch file and try again");
                                        break;
                                  }
                                  else
                                  {
                                                //do something here
                                  }
                            }
                            else{}      //no errors

                            }//end for
                    }//end inner try
                    catch(IllegalArgumentException ee)
                    {

                    }
                    catch (IOException e)
                    {

                    }
                    finally{}
                  }
            }
            catch (IOException e)
        {

        }
        finally{}
      }
Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

>> String strBatchPath="full-path-to-executable-bat-here";

seems like a strange directory name ...
When I run your code from the command line (fixed here and there -- I think you cut a little too much), it runs from the directory where the class files are.  I put a main around it and didn't use the JOptionPane, so the class is just a main which runs the run() method you posted above.

However, the executed class  identified by full-path-to-executable-bat-here in my test has a main program.  The error message you're getting says that there isn't a main program in the java class that you're trying to execute.

I don't know why you can get this to work from the Windows run dialog -- a main class is there or it isn't.

Does the .bat file execute correctly on its own?  If the program being called from within the .bat file needs a classpath, then that would be the place to define the required classpath for that program.
this example worked fine for me...

my batch file contained:

REM This is a test and it was called test.bat.  it existed under root directory too...
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
public class Main {
    
    static String strBatchPath = "test.bat";
    static String strBatchOutput = "";
    static Process p;
    static BufferedReader stdInput;
    static OutputStream stdOut;
    static BufferedReader stdError;
    
    public Main() {
    }
    
    public static void main(String[] args) {
        try {
            p = Runtime.getRuntime().exec(strBatchPath);
            
            try {
                stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
                stdOut = p.getOutputStream();
                stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
                
                if (stdInput.readLine() != null) {
                    System.out.println("Contents are: " + stdInput.readLine());
                } else {
                    System.out.println("failed to read contents...");
                }
            } catch(IllegalArgumentException ee) {
                ee.printStackTrace();
            } catch(IOException e) {
                e.printStackTrace();
            }
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

Open in new window

from my output window i see this:

init:
deps-jar:
Compiling 1 source file to C:\Java\Batch-File-Examples\build\classes
compile:
run:
Contents are: C:\Java\Batch-File-Examples>REM This is a test
BUILD SUCCESSFUL (total time: 0 seconds)


Ellandrd
If you're using a batch file to launch it, make sure the classpath is set in there. Use absolute paths then then batch file can be relocated
Avatar of mark_667
mark_667

ASKER

In order to replicate this the batch file needs to add some jars to a classpath and execute a class file in one (long) command. Sorry if I cut too much, forgot about the JOptionPane, feel free to replace that with a System.err.println() or if you like JOptionPanes replace g_parentFrame with newJFrame() it shouldn't affect the logic. The bat does execute on it's own and works fine, it's just invoking it from the code that gives me problems. And despite what the error says I'm almost certain it does have a main().

>> If the program being called from within the .bat file needs a classpath, then that would be the place to define the required classpath for that program.

the problem is, that's relative to the batch file not the program I need to run the batch file which is why I tried Process o.

I have a working batch file wit relative paths and another where I tried to recreate it with absolute paths but that gives me a class not defined error when executed manually:

java.io.IOException: CreateProcess: C:\Test.bat error=2
      at java.lang.Win32Process.create(Native Method)
      at java.lang.Win32Process.<init>(Unknown Source)
      at java.lang.Runtime.execInternal(Native Method)
      at java.lang.Runtime.exec(Unknown Source)
      at java.lang.Runtime.exec(Unknown Source)
      at java.lang.Runtime.exec(Unknown Source)
      at java.lang.Runtime.exec(Unknown Source)
      at Main.main(Main.java:22)

using the above code. Executing it on the batch with relative paths merely prints the contents of the file without executing it.

Any further thoughts would be welcome
can we see all your code plus your batch file contains please.
Putting a classpath on the call to your initial java program does not help with the classpath for the program being called within the .bat file.  

The classpath for executing the .bat program doesn't have anything to do with relative or absolute paths -- the classpath in the command line environment must have the paths of all required jars defined within it, and they all must be completely defined.  If your classpath declaration in your .bat file is relative, then in the .bat file you'll need to cd to the directory where the .bat file resides, and then execute the commands to set the classpath.

>>I'm almost certain it does have a main().
Something that is trying to execute does not have a main(args[]).  Whether that is the program you want is not yet clear.

I'm not sure we need to see all your code, but it would help at this point to see the .bat file, if you still cannot make it work.
>>the classpath in the command line environment must have the paths of all required jars defined within it

(Which is what i've just said)
>>(Which is what i've just said)
I know -- your and ellandrd's comments after mine are just what I said, too.  I suppose it can help to have the information repeated -- maybe a different wording makes it more clear.
Yes - no problem ;-)
>>I suppose it can help to have the information repeated -- maybe a different wording makes it more clear.

and gets the point across...
I'm afraid I can't post the actual contents of the batch file but the one which works when executed manually (with relative paths) but not with my code is of the form:

java -cp  bin;lib\jar1.jar;lib\jar2.jar; com.company.test.myclass param1 param2 param3

This runs up fine manually and the parameters are all passed in correctly.
I executed a bat file with absolute paths (my own which I use to launch my Java app) using ellanded's code and it worked fine running up an instance of my program, so that confirms it is a bat file problem. I've tried the following:

set var=C:\AppDir

set var=%var%;bin
set var=%var%;%var%\lib\jar2.jar
set var=%var%;%var%\lib\jar2.jar
set var=%var%;%C:\path-to-dir-that-contains-apps-im-trying-to-launch-here

C:\j2sdk1.4.2_13\bin\java -classpath var C:\path-to-dir-that-contains-apps-im-trying-to-launch-here\com\company\test\myclass param1 param2 param3

I've also tried specifying the bin directory:

here\bin\com

but it doesn't seem to make any difference, and

C:\j2sdk1.4.2_13\bin\java -classpath var C:\path-to-dir-that-contains-apps-im-trying-to-launch-here\com.company.test.myclass param1 param2 param3

myclass actually resides in C:\path-to-dir-that-contains-apps-im-trying-to-launch-here\bin\com\company\test

I am certain that the paths to the jars are correct. Did I mention I hate batch files?
>>set var=%var%;bin

will leave you with the following path

C:\AppDir;bin

which is probably wrong. All you need to do is something like

set CLASSPATH=C:\AppDir\lib\a.jar;C:\AppDir\lib\b.jar

You can make refinements with placeholders once it's working

you have probably mentioned this above but why are you adding the JAR's to the classpath using a batch file?  why cant you add them the project and leave out all this mess of using batch files...

have you consider using the JAR file that gets created when building and compiling your java application?  if your using netbeans a JAR file is generated for you automatically.  if your using eclipse you can use ANT to generate a JAR file automatically.  then use this is JAR file instead of calling the path your your class:

C:\path-to-dir-that-contains-apps-im-trying-to-launch-here\com\company\test\myclass



CEHJ is right above - how you have set your batch file is wrong.

im not great a batch files but i would have done something like this:

set app_home=C:\AppDir
set lib_1=%app_home%\lib\jar2.jar
set lib_2=%app_home%\lib\jar2.jar
set app_settings = %app_home%;%lib_1%;%lib_2%;
set classpath = %app_settings%;

have you set a JAVA_HOME as a environmental variable in your PATH that points to C:\j2sdk1.4.2_13\bin\

if you have why cant you just do this in your batch file:

set app_class = C:\path-to-dir-that-contains-apps-im-trying-to-launch-here\com.company.test.myclass
java -classpath var %app_class% param1 param2 param3

if not, then it would be very helpful...



>>Did I mention I hate batch files?

No
am i correct in saying your using a Java app to execute and read the output from a batch file that in itself executes another application?
I've been tinkering and I've got:

set app_home=C:\AppDir
set lib_1=C:\AppDir\lib\jar1.jar
set lib_2=C:\AppDir\lib\jar2.jar

set classpathVar = %app_home%;%lib_1%;%lib_2%;%lib_3%;%lib_4%;%lib_5%;%lib_6%;%lib_7%;

set app_class = C:\path-to-dir-that-contains-apps-im-trying-to-launch-here\com.company.test.myclass

java %apps_class% param1 param2 param3

pause;

and:

java -classpath classpathVar %apps_class% param1 param2 param3

and

java -classpath %classpathVar% %apps_class% param1 param2 param3

all give:
Exception in thread "main" java.lang.NoClassDefFoundError: C:\path-to-dir-that-contains-apps-im-trying-to-launch-here\com.company.test.myclass

>>am i correct in saying your using a Java app to execute and read the output from a batch file that in itself executes another application?

yes, you see the bat file I'm trying to execute launches a java command line utility which I need to make repeated calls to in my program. My program is itself launched by a batch file like the one I posted earlier as it's the easiest way for the user to launch it by double clicking a batch or shell file without having to use special installer software or compiling it to native, etc.

Going back to part of my original question, if I do need to execute the class file directly can I do so without using JNI (I don't want to have to compile the C++ part of it with GCC and the rest with javac every time I want to do a build)? There must be a way of invoking the main() of another java class from another package without JNI.
>>C:\path-to-dir-that-contains-apps-im-trying-to-launch-here

should be part of your classpath - it isn't
Exception in thread "main" java.lang.NoClassDefFoundError: C:\path-to-dir-that-contains-apps-im-trying-to-launch-here\com.company.test.myclass

This one is a bit&h to track down...

one way is to print out the classpath to see if there is any mistakes in it...

System.out.println(System.getProperty("java.class.path ));

you'll need to import java.util.Properties;

no a side note, double check all names, paths, spellings etc
Have you tried adding a
cd c:\path-you-execute-batch-file-from-when-it-works
at the top of your .bat file?

Also -- you said that you've tinkered with your original .bat file -- does the new .bat file execute standalone?  And from which directory do you execute it when it works?

I see you've tried to remove various dependencies in the new version of the .bat file, but it seems that the [local path]/bin directory has been removed from your new .bat file's classpath.  Have you tried adding it back in -- but correctly, as CEHJ pointed out?
>>
Have you tried adding a
cd c:\path-you-execute-batch-file-from-when-it-works
at the top of your .bat file?
>>

You don't actually need to cd. That simply is part of the CLASSPATH
>>You don't actually need to cd. That simply is part of the CLASSPATH

Of course not.

But if mark_667 is having trouble setting up his environment fully in his .bat file, it often helps to cd to the directory.  
>>Going back to part of my original question, if I do need to execute the class file directly can I do so without using JNI (I don't want to have to compile the C++ part of it with GCC and the rest with javac every time I want to do a build)? There must be a way of invoking the main() of another java class from another package without JNI.

The main requires its own instance of the JVM, so you have to execute it.  You could certainly exec the main of the Java program similarly to how you're running your .bat file, with something like:

p = Runtime.getRuntime().exec("java C:\path-to-dir\com.company.test.myclass " + param1 + " " +  param2 + " " +  param3);
>>Going back to part of my original question, if I do need to execute the class file directly can I do so without using JNI (I don't want to have to compile the C++ part of it with GCC and the rest with javac every time I want to do a build)? There must be a way of invoking the main() of another java class from another package without JNI.

Maybe there isn't a main?  Your question here implies that you're really running a C++ executable which is invoking a Java class -- not a Java main program.  So perhaps you want to include the jar or class files of the actual Java class in your original program, import the class for the method you want to call, and call it?
>>why are you adding the JAR's to the classpath using a batch file?  why cant you add them the project and leave out all this mess of using batch files...

I can't expect the people who are going to be using the software to run up an IDE every time they want to use it!

>>have you consider using the JAR file that gets created when building and compiling your java application?

That is a good idea and I have thought of it but right now we need to do it like this.

>>you said that you've tinkered with your original .bat file

Actually I'm leaving the original well alone as it's the only working one at the moment, I'm working on a copy that does the same as the original but with absolute instead of relative paths so my app can launch it. At the moment, the new version doesn't execute without errors.

as some of you have pointed out I did miss out the bin directory, I have now added this in.

mrcoffe365:
>>The main requires its own instance of the JVM, so you have to execute it.  You could certainly exec the main of the Java program similarly to how you're running your .bat file, with something like:

p = Runtime.getRuntime().exec("java C:\path-to-dir\com.company.test.myclass " + param1 + " " +  param2 + " " +  param3);

I have tried this, but I get this in the error output:
java.lang.NoClassDefFoundError: C:\path-to-dir\com/company/test/myclass
Exception in thread "main"

nice try though

>>Maybe there isn't a main?  Your question here implies that you're really running a C++ executable which is invoking a Java class -- not a Java main program.  So perhaps you want to include the jar or class files of the actual Java class in your original program, import the class for the method you want to call, and call it?

I think we're getting a little confused here. The method I had in mind is detailed here:
Launching Java Applications from Other Programs @ JAVA DEVELOPER'S JOURNAL
http://java.sys-con.com/read/35718.htm
which requires a native method. As for including the jar or class files of the program I'm trying to execute, that's an interesting idea but I may not be able to do it.
Can you print the classpath currently in use?
CEHJ, I put the line:
System.out.println(System.getProperty("java.class.path"));
right after my process statement and got back:

C:\full-path-to-my-program-sources;C:\Program Files\Eclipse\eclipse\plugins\org.junit_3.8.1\junit.jar;
followed by a load of jars my program uses and which the class file being launched through the bat file needs. In fact, to see what the difference was, I put one before and after the process exec command and they are identical. Java must check to see if it is already listed before adding it.

I tried executing a bat file with:
java C:\path-to-dir\com.company.test.myclass param1 param2 param3
and
java com.company.test.myclass param1 param2 param3

unfortunately, that didn't work either (no output).

Interestingly it seems to execute one line of the bat file per iteration and the bin directory does't seem to be bring added to the classpath, nor is the class, it's only adding the jar files.

Here's what the output looks like:
C:\Me>set CLASSPATH = C:\AppDir\lib\jar1.jar;C:\AppDir\lib\jar2.jar;C:\AppDir\bin; C:\AppDir\com.company.test.myclass;
C:\Me>C:\AppDir\lib\jar1.jar;C:\AppDir\lib\jar2.jar;
The 1st line is the bat file command being executed, the second lists the classpath. They are being added:

set app_home=C:\AppDir
set lib_2=C:\AppDir\lib\jar2.jar
set bin=C:\AppDir\bin
set class=C:\path-to-dir\com.company.test.myclass

set CLASSPATH = .;%app_home%;%lib_1%;%lib_2%;%bin%;%class%;
>>In fact, to see what the difference was, I put one before and after the process exec command and they are identical.

They will be. The classpath (which is STILL wrong) in the batch file has nothing to do with the one in the app from which you invoke it. Apart from which, effectively the classpath for any app is effectively immutable. Once the jvm has read it, game over
Is it possible that your java program is not in a package?  If so, then when you try to execute your java program from somewhere other than its local directory (i.e., where classpath=.) then your class file will not be found.  See this doc from Sun for some information on how classes are found:
http://java.sun.com/javase/6/docs/technotes/tools/findingclasses.html

You can solve this by putting
cd [your java app dir here]
at the top of your .bat file.

Long term, when we create software for general use, we create packages.  Then the classpath can be set to refer to the location of the package.
CEHJ>>The classpath (which is STILL wrong) in the batch file has nothing to do with the one in the app from which you invoke it.

I was printing the wrong one? Oops! Can you tell me how it should be set?

mrcoffe360: I followed your advice and got a slightly different error message, it now tells me I'm using the wrong name.


cd C:\path-to-dir\com\company\test
dir

java myclass param1 param2 param3
rem java -classpath . EMVCardEmulator card.db 0986764312000101 00
rem makes no difference

pause;

gives:

C:\>cd C:\path-to-dir\com\company\test

C:\path-to-dir\com\company\testdir
 Volume in drive C has no label.
 Volume Serial Number is 081F-2784

 Directory of C:\path-to-dir\com\company\test
 
22/11/2007  16:29    <DIR>          .
22/11/2007  16:29    <DIR>          ..
10/08/2004  08:55             5,320 anothter.class
10/08/2004  08:55             2,350 another1.class
10/08/2004  08:55             4,794 myclass.class
10/08/2004  08:55             4,588 another2.class
               4 File(s)         17,052 bytes
               2 Dir(s)  13,900,877,824 bytes free

C:\path-to-dir\com\company\test>java myclass param1 param2 param3
Exception in thread "main" java.lang.NoClassDefFoundError: myclass (wron
g name: com/company/test)
        at java.lang.ClassLoader.defineClass0(Native Method)
        at java.lang.ClassLoader.defineClass(Unknown Source)
        at java.security.SecureClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.access$100(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClassInternal(Unknown Source)

C:\>pause;
Press any key to continue . . .

I also tried:

@echo off

cd C:\path-to-dir\com\company\test

dir

set MY_HOME=C:\path-to-dir\

set MY_CLASSPATH=%MY_HOME%\lib\jar1.jar
set MY_CLASSPATH=%MY_CLASSPATH%;%MY_HOME%\lib\jar2.jar

java -classpath %MY_CLASSPATH%; myclass param1 param2 param3
pause;

The command line output for this is the same as above.

Thanks to mrcoffe360, CEHJ and ellandrd for sticking with me on this, it's a lon thread but hopefully we're getting closer now.
>>Exception in thread "main" java.lang.NoClassDefFoundError: myclass (wron
g name: com/company/test)

I think you need to cd to d:\path-to-dir , not to the place where the .class file is.  Then, with the classpath set correctly -- that is, to . or d:\path-to-dir, it will find com.company.test .

Also -- this message says that you are trying to execute class "myclass" when the actual name in the file is com.company.test .

It's a little hard to debug this, because I assume that you are retyping key parts of the code and the error messages, and it's not always clear whether you have chosen the right replacements for the real data.
>>I was printing the wrong one? Oops! Can you tell me how it should be set?

Well - only if you print the RIGHT one ;-)
And don't cd anywhere. You have enough problems with paths without changing them dynamically ;-)
I agree with CEHJ is saying - i dont think you need to change the directory
mrcoffe365:
>>I think you need to cd to d:\path-to-dir , not to the place where the .class file is.  Then, with the classpath set correctly -- that is, to . or d:\path-to-dir, it will find com.company.test .

Also -- this message says that you are trying to execute class "myclass" when the actual name in the file is com.company.test .

I tried you suggestion and got back a different NoClassDefFoundError which I think is refering to a datatype used by the program, in which case it's a classpath problem.

>>It's a little hard to debug this, because I assume that you are retyping key parts of the code and the error messages, and it's not always clear whether you have chosen the right replacements for the real data.

I'm sorry about this I try to make sure it's accurate.


>>And don't cd anywhere. You have enough problems with paths without changing them dynamically ;-)

CEHJ: I wouldn't but I can't find a way to get the same result without cd ing.
>>CEHJ: I wouldn't but I can't find a way to get the same result without cd ing.

You just need to be more accurate in your reading of the comments here and your replies to them. Please post the latest version of your batch file
>>You just need to be more accurate in your reading of the comments here and your replies to them. Please post the latest version of your batch file

I'm sorry if I'm misunderstanding anyone I do always read any and all posts made since my last comment and try any suggestions in them before posting. I've got a few (about 10 now) different versions but they mostly give the same output, see below.

cd %CD%\bin\

set app_home=C:\app-dir\
set lib_1=%CD%\lib\jar1.jar
set lib_2=%CD%\lib\jar2.jar
set lib_3=%CD%\lib\jar3.jar
set bin=%CD%\bin
set class=%CD%\bin\com.company.test.myclass
set CLASSPATH = .;%app_home%;%lib_1%;%lib_2%;%lib_3%;%bin%;%class%;

java %class% param1 param2 param3
pause;

and

@echo off

cd %CD%\bin\

set My_CLASSPATH=%My_CLASSPATH%;%CD%\lib\jar1.jar
set My_CLASSPATH=%My_CLASSPATH%;%CD%\lib\jar2.jar
set My_CLASSPATH=%My_CLASSPATH%;%CD%\lib\jar3.jar
set My_CLASSPATH=%My_CLASSPATH%;\bin\com\company\test\

java -classpath %My_CLASSPATH%; com.company.test.myclass param1 param2 param3

pause;

Without the cd command in the last example, I get the NoClassDefFoundError for my class not name-of-some-ther-class-thats-not-in-directory.

Executing them as they are above (i.e. with the cd command), I get:
Exception in thread "main" java.lang.NoClassDefFoundError: com/company/test/name-of-some-ther-class-thats-not-in-directory-here
Press any key to continue . . .

In case you didn't notice, I've just discovered the %CD% pseudo variable which simplifies things a bit. The others give the same error but for myclass so I'm guessing these have got further. In case you're wondering I have included all the jars in the \lib directory.
>>set My_CLASSPATH=%My_CLASSPATH%;%CD%\lib\jar1.jar

where do you set MY_CLASSPATH  & CD ?
As i've said umpteen times now:

>>
set class=%CD%\bin\com.company.test.myclass
set CLASSPATH = .;%app_home%;%lib_1%;%lib_2%;%lib_3%;%bin%;%class%;
>>

'com.company.test.myclass' is NOT part of a classpath, it's the fully-qualified name of your class (although class names should begin with a capital letter)

The correct classpath for that particular class is the absolute location of that 'bin' directory it's in.
As i also said before. DO NOT cd in your batch file - it will create complexity that's unnecessary and will lead to problems. Get rid, thoroughout, of %CD% which is something different and could lead to even more problems
OK, I finally got it to execute manually with:

@echo off

cd C:\path-to-dir\bin\

set My_CLASSPATH=%My_CLASSPATH%;C:\path-to-dir\lib\jar1.jar
set My_CLASSPATH=%My_CLASSPATH%;C:\path-to-dir\lib\jar2.jar
set My_CLASSPATH=%My_CLASSPATH%;C:\path-to-dir\lib\jar3.jar
set My_CLASSPATH=%My_CLASSPATH%;\bin\com\company\test\

java -classpath %My_CLASSPATH%; com.company.test.myclass C:\path-to-dir\param1 param2 param3

pause;


Sorry CEHJ, I couldn't get it to work without the cd command. I don't see how %CD% could lead t more problems as you say but I put the full paths in anyway and it works (except when I try to execute it through my app).

When I hit:
strOutput = stdInput.readLine();
it seems to execute it but never comes back. The same code can sucessfully execute a different bat file (of the same form as mine and also using absolute paths). The code I'm using is:
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
 
public class FuncTest
{
	public static void main(String[] args)
	{
		String strPath="C:\\full-path-to-batch-file here";
		String strOutput="";
		String strError="";
 
	        try
	        {
	            Process p = Runtime.getRuntime().exec(strPath);
	 
	            BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
	            BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
	 
	            // read the output from the command
	            while (strOutput!=null)
	            {
	            	
	            	if(strOutput.length()<1) {}
	            	else
	            	{
	            		System.out.println(strOutput);
	            	}
	            	strOutput = stdInput.readLine();
	            }
	 
	            strError = stdError.readLine();
	            
	            if(strError!=null)
	            {
	                System.out.println("An error occured\n");
	                
	                while (strError!=null)
	                {
	                    System.out.println(strError);
	    	            strError = stdError.readLine();
	                }
	            }
	            else {}
	        }
	        catch (IOException e)
	        {
	            System.out.println("An IOException occured");
	            e.printStackTrace();
	            System.exit(-1);
	        }
	}
}

Open in new window

try this:
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
 
public class FuncTest
{
        public static void main(String[] args)
        {
                String strPath="C:\\full-path-to-batch-file here";
                String strOutput="";
                String strError="";
 
                try
                {
                    Process p = Runtime.getRuntime().exec(strPath);
         
                    BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
                    BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
         
      
                    while (strInput != null)
                    {
                       System.out.println(stdInput.readLine());
           
                    }
         
                    if(stdError.readLine() == null)
                    {
                        System.out.print("An error occured\n");
                        
                            System.out.println(stdError.readLine());
    
                    }
                   
                }
                catch (IOException e)
                {
                    System.out.println("An IOException occured");
                    e.printStackTrace();
                    System.exit(-1);
                }
        }
}

Open in new window

sorry this line:

if(stdError.readLine() == null)

 should be:

if(stdError.readLine() != null)
Removing the @echo off means the program can output what it's executing, only now it hangs after it's executed the java command, I don't get any output from the application back.
if the batch file fails you should get some sort of error message appearing..

add @echo off back in and run through dos window
That's the problem, the bat file runs fine in DOS but right after the program's output the line with the java command on it, it hangs at: strOutput = stdInput.readLine(); I don't think it's failing when executed from my program either.
>>strOutput = stdInput.readLine();

did you even try the changes i made above on ID:20350691 ?  i removed the "strOutput = stdInput.readLine();"
If it hangs there, then it's waiting for input.

I suggest you modify the way you read from stdInput and stdError to be something like this (a common way to handle it in Java):

      while( ( strBatchOutput = stdInput.readLine() ) != null ) {
            System.out.println("after readLine strBatchOutput = " + strBatchOutput);
        }

      while( (strBatchErrorOutput = stdError.readLine() ) != null ) {
            System.out.println("stdError: " + strBatchErrorOutput);
      }

>>Sorry CEHJ, I couldn't get it to work without the cd command.

That's because the classpath was wrong (and still is) but i've pointed out the problem so many times with no effect, so i'm throwing in the towel now ;-)
CEHJ: If the classpath is incorrect how does it run correctly manually?

>>As i've said umpteen times now:

>>>>
set class=%CD%\bin\com.company.test.myclass
set CLASSPATH = .;%app_home%;%lib_1%;%lib_2%;%lib_3%;%bin%;%class%;
>>>>

>>'com.company.test.myclass' is NOT part of a classpath, it's the fully-qualified name of your class (although class names should begin with a capital letter)

neither \bin\com.company.test.myclass
nor \bin\com.company.test
are part of my classpath.

      Either way it seems to be executing now both manually and through my program as I've already said, the problem now is getting back output from it. When executed it does stop and wait for you to enter data but why can't I see this in strOutput? I need to be able to read the results it outputs or it's no good to me.

mrcoffe365: I tried the code you posted and the only difference seems to be that I now get a
after readLine strBatchOutput =
between each line.

ellandrd: I tried the code snippits you posted and they do compile the working bat file but I still don't get any output from it. Here's the last part of the output I get using the latest code you posted:

C:\Me>java -classpath C:\app-dir\lib\jar1.jar;C:\app-dir\lib\jar2.jar;C:\app-dir\lib\jar3.jar; com.company.test.myclass C:\app-dir\param1 param2 param3

which is as far as I've got with aynthing so far.
>>
neither \bin\com.company.test.myclass
nor \bin\com.company.test
are part of my classpath.
>>

Well they ARE - you set them here

>>
set class=%CD%\bin\com.company.test.myclass
set CLASSPATH = .;%app_home%;%lib_1%;%lib_2%;%lib_3%;%bin%;%class%;
>>

(which you've just quoted yourself!)

The reason it works is that the incorrect part of the classpath is simply ignored. You have fixed that broken part by CDing (unnecessarily)

ASKER CERTIFIED SOLUTION
Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks you! I was just about to give up on this.
only accepting CEHJ's last comment is abit unfair dont you think?
:-)