views:

315

answers:

4

I'm trying to launch a Java app from a C++ app using the following code:

#include <windows.h>
#include <memory.h>
#include <tchar.h>

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) {
    STARTUPINFOW        siStartupInfo;
    PROCESS_INFORMATION piProcessInfo;

    memset(&siStartupInfo, 0, sizeof(siStartupInfo));
    memset(&piProcessInfo, 0, sizeof(piProcessInfo)); 

    if (CreateProcess(TEXT("c:\\java\\jre\\bin\\java.exe"), TEXT("-jar testapp.jar"), NULL, NULL, false, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &siStartupInfo, &piProcessInfo) == false) {
        MessageBox(NULL, L"Could not load app", L"Error", 0);
    }

    CloseHandle(piProcessInfo.hProcess);
    CloseHandle(piProcessInfo.hThread);

    return 0;
}

When I build and run the program I get the following error:

Exception in thread "main" java.lang.NoClassDefFoundError: testapp/jar
Caused by: java.lang.ClassNotFoundException: testapp.jar
        at: java.net.URLClassLoader$1.run(Uknown Source)
        at: java.security.AccessController.doPrivileged(Native Method)
        at: java.net.URLClassLoader.findClass(Uknown Source)
        at: java.lang.ClassLoader.loadClass(Uknown Source)
        at: sun.misc.Launcher$AppClassLoader.loadClass(Uknown Source)
        at: java.lang.ClassLoader.loadClass(Uknown Source)
Could not find the main class: testapp.jar. Program will exit.

The testapp.jar file is a runnable JAR file exported from an Eclipse project with a single class in it:

public class Test {
    public static void main(String[] args) {
        System.out.println("test");
    }
}

The EXE and JAR file are in the exact same folder, and I'm running the EXE from the command line. If I run the JAR directly by putting c:\java\jre\bin\java.exe -jar testapp.jar into the command-prompt everything works as expected.

Does anyone have any idea what's going on here?

EDIT: Thank you all for your help, but it looks like I've got it working now.

+1  A: 

The documentation for CreateProcess() specifies for the parameter lpCurrentDirectory:

The full path to the current directory for the process. The string can also specify a UNC path.
If this parameter is NULL, the new process will have the same current drive and directory as the calling process.

You excerpt is missing a definition for path, but most likely it is set up incorrectly.

Georg Fritzsche
Zoltan
A: 

Try specifying the directory of the JAR after -jar. It could have to do with your current working directory...

Scott Smith
Tried that, still no luck :(
Zoltan
+3  A: 

Solved it. I used:

if (CreateProcess(TEXT("C:\\Program Files\\Java\\jre6\\bin\\java.exe"), TEXT(" -jar test.jar"), NULL, NULL, false, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &siStartupInfo, &piProcessInfo) == false) {
        MessageBox(NULL, L"Could not load app", L"Error", 0);
    }

Whereas you've used:

if (CreateProcess(TEXT("C:\\Program Files\\Java\\jre6\\bin\\java.exe"), TEXT("-jar test.jar"), NULL, NULL, false, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &siStartupInfo, &piProcessInfo) == false) {
        MessageBox(NULL, L"Could not load app", L"Error", 0);
    }

which, when I used it, replicates your error. The difference is a space preceding the -jar switch and why that should be, I don't know, I stumbled upon it in error!

Ninefingers
Ah, that does indeed work! A big green tick for you!
Zoltan
I'll be honest, why is currently eluding me. I'll update the answer if I find out.
Ninefingers
That sneaky whitespace ...
Georg Fritzsche
@gf I know. Discovered via an editing mistake, so I don't really deserve +1 or the answer but I've hit the rep limit anyway. Any ideas as to why this is?
Ninefingers
@Ninefingers: A quick test shows that the Win32 API is so clever that it passes an empty entry as the first entry for `argv` if you use a leading space ...
Georg Fritzsche
@gf. Oh. Interesting... I did try the argument string as java.exe -jar ... with the program string as-is, but that produced the error again. Hmmm.
Ninefingers
+1  A: 

I just had to change the way I was calling CreateProcess:

wchar_t *command = (wchar_t*)calloc(512, sizeof(wchar_t));

wsprintf(command, TEXT("c:\\java\\jre\\bin\\java.exe -jar testapp.jar"));

if (CreateProcess(NULL, command, NULL, NULL, false, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &siStartupInfo, &piProcessInfo) == false) {
Zoltan
haha, now you can accept your own answer!
Ninefingers