1

I've created a Windows registry entry in HKEY_CLASSES_ROOT* with the value: "C:\test.exe" "%1" to create a new right-click context menu entry that passes the filepath of the clicked file to the registered test.exe. Inside the test.exe a dll-file is loaded that should inject into an already running jvm to call a method and pass the filepath. The problem is that the .dll does not find a JVM instance although it is running in a while-loop (prototype). Could you please help me to solve that problem? How do I have to access the JVM? Thanks

.java:

public class Main
{
    public static void main(String[] args)
    {   
        while(true)
        {

        }
    }

    public static void readAndOutputFilePath(String result)
    {       
        System.out.println("Java result: "+result); 
        try
        {
            System.in.read();
        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

.dll:

HMODULE m_hDllInstance = LoadLibrary("jvm.dll");
if( m_hDllInstance == 0)
{
    printf("The jvm.dll could not be found");
    getchar();    
}
else
    printf("jvm.dll found");


JavaVM *jvm;   
JNIEnv *env;  

typedef jint (JNICALL * GetCreatedJavaVMs)(JavaVM**, jsize, jsize*);
GetCreatedJavaVMs jni_GetCreatedJavaVMs = (GetCreatedJavaVMs)GetProcAddress(m_hDllInstance, "JNI_GetCreatedJavaVMs");

jint size = 1;
jint vmCount;

jint ret= jni_GetCreatedJavaVMs(&jvm, size, &vmCount);

cout << endl << "GetCreated: " << vmCount << endl;
getchar();

jint rc = jvm->AttachCurrentThread((void **) & env, NULL);

jclass cls = env->FindClass("Main");
jmethodID mid = env->GetStaticMethodID(cls, "readAndOutputFilePath", "(Ljava/lang/String;)V");

jstring resultString = env->NewStringUTF(path);
env->CallStaticVoidMethod(cls, mid, resultString);
...
user3422749
  • 62
  • 1
  • 9

2 Answers2

1

There is nothing special about communications with a Java program running in an independent, separate process. Any IPC facility supported by Java can be used. Local sockets is the first thing that comes to mind, but also shared memory and plain old filesystem.

JNI is probably irrelevant, as your Java program is in a separate process - unless you want to use some windows-specific communication modes such as OLE. In that case you'll need to write your communication protocol in another language an load them into your Java program.

  • Thanks for your hints. I've implemented a prototype with sockets and it works :) but I would like to have a low latency version without network communication. I've tried sth. with shared memory / memory mapped files. But how could I manage it that process 1 knows that process 2 has written a clicked filepath to the shared memory? I need some kind of listener (polling / event listener) that tells me when new data was written to the shared mem... – user3422749 Apr 16 '14 at 17:29
  • sockets on 127.0.0.1 are low enough latency for anything that involves UI. –  Apr 16 '14 at 20:43
0

You don't seem to understand what a JVM actually is. It is itself a DLL that is loaded into the process. It isn't a 'thing' that's just 'out there'. Using the JNI Invocation API you can start one, and you won't find 'the' JVM in a .exe that you just started yourself unless you do so.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Hi but in another post a user has achieved that: [link](http://stackoverflow.com/questions/22441878/attach-to-already-running-jvm/22450463#22450463). But I don't understand the way he has achieved that and my hope was that somebody could help me to solve my problem in the above code snippet. Do you know another way to get the filepath of the context menu into an already running JVM? I also thought about passing the filepath to a Java program that uses RMI to call the method of the already running Java program but that's too complex and 'heavyweight' for my problem... Thanks – user3422749 Apr 14 '14 at 10:12
  • I think what you are trying to do is start a jvm and your class file from an native program. This has nothing to do with injecting any code. You need to first create a C executable that leverages JNI to start a JVM. There are lots of examples out there to do that. see: http://www.inonit.com/cygwin/jni/invocationApi/c.html – Alex Barker Apr 14 '14 at 22:55
  • One more thing, Why are you trying to a file path from a context menu!? A context menu is some on screen widget that could be created by any running application. What I am getting at is that you have run into a problem trying to solve your original problem incorrectly. – Alex Barker Apr 14 '14 at 22:59
  • My original problem is: I have a Java program that is already running (in background). I've created a menu entry in windows explorer context menu with an entry in windows registry (description above). Now I would like to get the filepath of the clicked file in my already running Java program to save some file information. How could I achieve this? My registry entry: "C:\test.exe" "%1" or another approach: java -jar "C:\test.jar" "%1" ... How could I pass the filepath of a clicked file to my already running Java prog? – user3422749 Apr 15 '14 at 17:10
  • I need sth. like this: (http://stackoverflow.com/questions/370114/how-can-i-add-a-context-menu-to-the-windows-explorer-for-a-java-application). The problem is, as I described above, that my Java prog. is already running. How could I pass the filepath? I already thought about a second Java prog that catches the filepath and communicates with the running prog (about RMI etc.). But I don't really like that kind of solution... – user3422749 Apr 15 '14 at 17:16