JNI: kein Zugriff auf VM in Callback-Methode eines Windows-Hooks

ThomasE

Neues Mitglied
Hallo

Ich versuche gerade Windows beizubringen, dass es bei jedem Tastendruck, egal ob meine Anwendung den Fokus hat oder nicht, eine Methode meines Java-Programms aufruft. Um dies zu realisieren, ruft meine Java-Anwendung beim Start die Methode
Code:
Java_autopilot_KeyboardHook_start
in meiner selbstgeschriebenen DLL (der C-Code befindet sich ein Stück weiter unten) auf, die die Methode
Code:
KeyboardProc
als Keyboard-Callback registriert. Soweit funktioniert alles und die
Code:
KeyboardProc
wird auch bei jedem Tastendruck aufgerufen. Mein Problem ist, dass ich in
Code:
KeyboardProc
nicht auf die JVM zugreifen kann. Jeder Aufruf über den javaVm-Pointer schlägt fehlt und auch
Code:
JNI_GetCreatedJavaVMs
gibt 0 gefundene VMs (nVMs) zurück :-(

Ermittelt man in der Methode "Java_autopilot_KeyboardHook_start" mit JNI_GetCreatedJavaVMs(...) die verfügbaren VMs, dann bekommt man die eine existierende zurückgegeben.

Habt Ihr eine Idee, wieso die VM für die Keyboard-Callback-Methode nicht existiert ?

Danke

Thomas


Code:
#pragma data_seg("myJVM")

JavaVM* javaVm = NULL;

#pragma data_seg()

#pragma comment(linker,"/SECTION:myJVM,RWS")


JNIEXPORT jint JNICALL JNI_OnLoad( JavaVM *vm, void *pvt ) {

   javaVm = vm;

   printf("JNI_OnLoad(): javaVm = %X\n", javaVm);

   return JNI_VERSION_1_2;
}


JNIEXPORT void JNICALL Java_autopilot_KeyboardHook_start(JNIEnv* env, jobject obj) {

   HHOOK hook;

   hook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, dllInst, 0);

   if (hook == NULL) {

      printf("hookErr = %d\n", GetLastError());

   } else {

      Sleep(5000);

      UnhookWindowsHookEx(hook);
   }
}

extern "C" __declspec (dllexport) LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam) {

   FILE* file;
   char* buffer = new char[255];
   jint result = 4711;
   JNIEnv* env;
   jsize nVMs = 4711;
   JavaVM * vmBuf;


   fopen_s(&file, "C://hook.txt", "a");

   sprintf_s(buffer, 255, "w = %10X l = %10X vm = %X\n", wParam, lParam, javaVm);

   fputs(buffer, file);

   result = JNI_GetCreatedJavaVMs(&vmBuf, 1, &nVMs);

   sprintf_s(buffer, 255, "JNI_GetCreatedJavaVMs: result = %X nVMs = %X\n", result, nVMs);

   fputs(buffer, file);

   result = javaVm->AttachCurrentThreadAsDaemon((void**)&env, NULL);

   sprintf_s(buffer, 255, "AttachCurrentThreadAsDaemon: result = %d\n", result);

   fputs(buffer, file);

   fclose(file);

   return CallNextHookEx(NULL, code, wParam, lParam);
}
 
T

trääät

Gast
das problem könnte sein das du versuchst den pointer auf die VM im globalen kontext der DLL abzulegen
Code:
#pragma data_seg("myJVM")
JavaVM* javaVm = NULL;
#pragma data_seg()
#pragma comment(linker,"/SECTION:myJVM,RWS")
ganz davon abgesehen das es bei mehrfach-instanzzierung logisch immer nur die letzte VM hätte ist das aber so leider nicht möglich ... gründe dafür finden sich in der JNI spezifikation ...
nimm also den VM-pointer einfach aus dem global-kontext raus (also entferne einfach die pragma-zeilen) und es sollte funktionieren ...

alternativ hier ein link zu nem global-hook : Java – Global (low level) Keyboard / Mouse Hook – JNI kSquared.de – Blog
 

Marco13

Top Contributor
Beim Überfliegen sehe ich nirgendwo ein "getEnv" ... Siehe auch http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/invocation.html#GetEnv

Ein Stück Code, ohne Gewähr...
Code:
    jint attached = globalJvm->GetEnv((void**)&env, JNI_VERSION_1_4);
    if (attached != JNI_OK)
    {
        globalJvm->AttachCurrentThread((void**)&env, NULL);
    }

    env->CallVoidMethod(...);

    if (attached != JNI_OK)
    {
        globalJvm->DetachCurrentThread();
    }
 

ThomasE

Neues Mitglied
Danke für Eure Antworten. Die geposteten URLs haben mich in die richtige Richtung gelenkt.

Der Grund warum es nicht funktioniert hat lag im Aufruf der Methode
Code:
SetWindowsHookEx
. In meiner ursprünglichen Version sah der Aufruf so aus:

Code:
SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, dllInst, 0);

Richtig ist aber ...

Code:
SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, dllInst, 0);

Übergibt man als erstes Argument WH_KEYBOARD, dann wird die Callback-Methode (KeyboardProc) von einem anderen Thread aus aufgerufen und von da aus hat man keinen Zugriff auf die bereits existierende VM.

Übergibt man als erstes Argument WH_KEYBOARD_LL, dann schickt Windows bei jedem Tastendruck an den Thread, in dem mit
Code:
SetWindowsHookEx
die Callback-Methode registriert wurde, eine Nachricht (z.B. WM_KEYDOWN). Somit muss man in diesem Thread auch eine Eventqueue einbauen, damit man diese Nachrichten verarbeiten kann. Da jetzt die Callback-Methode vom dem Thread ausgeführt wird, der auch die Callback-Methode bei Windows registriert hat, hat man auch Zugriff auf die VM.

Den funktionierenden Code habe ich Euch hier noch mal gepostet. Vielleicht hilft es ja irgendjemanden in Zukunft.

Code:
JavaVM*		javaVm		= NULL;
HHOOK		hook		= NULL;
jclass		javaClass;
jobject		javaObject;
jmethodID	methodId;
DWORD		hookThreadId	= NULL;

JNIEXPORT void JNICALL Java_autopilot_KeyboardHook_start(JNIEnv* env, jobject obj) {
	       
	MSG message;
	
	env->GetJavaVM(&javaVm);

	javaObject		= obj;
	javaClass		= env->GetObjectClass(obj);
	methodId		= env->GetMethodID(javaClass, "keyEvent", "(III)V");
	hookThreadId		= GetCurrentThreadId();

	if (methodId != NULL) {

		hook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, dllInst, 0); 
	
		if (hook == NULL) {
		
			printf("hookErr = %d\n", GetLastError());

		} else {

			while(GetMessage(&message, NULL, 0, 0)) {
				DispatchMessage(&message);
			}
		}
	}
}

JNIEXPORT void JNICALL Java_autopilot_KeyboardHook_stop(JNIEnv* env, jobject obj) {

	if (hook != NULL) {
		
		PostThreadMessage(hookThreadId,WM_QUIT,0,0L);
		hook = NULL;
		printf("unhooked the callback method\n");
	}
}

extern "C" __declspec (dllexport) LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam) {
	
	jint			result;
	JNIEnv*			env;
	KBDLLHOOKSTRUCT*	data;

	result = javaVm->AttachCurrentThread((void **)&env, NULL);
	
	if (result == JNI_OK) {
		
		data = (KBDLLHOOKSTRUCT*)lParam;
		env->CallVoidMethod(javaObject, methodId, allowedKeys[keyCount-1], data->vkCode, data->scanCode);
	}

	return CallNextHookEx(NULL, code, wParam, lParam);
}
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
M Kein Zugriff auf microSD Karten Allgemeine Java-Themen 4
D Eclipse Kein Zugriff auf Inhalt einer referenzierten .jar Allgemeine Java-Themen 5
D Kein Zugriff auf WebService ausser localhost Allgemeine Java-Themen 4
Haave Audio Device Unavailable: Kein gleichzeitiger Zugriff auf Soundsystem möglich Allgemeine Java-Themen 7
J Kein Zugriff auf Klassen im Default Package Allgemeine Java-Themen 8
A Dateistatus abfragen und Datei löschen sobald kein Zugriff Allgemeine Java-Themen 7
Zrebna SonarLint: Warum kein Null-Referencing-CodeSmell-Hint hier? Allgemeine Java-Themen 23
M Kein Scanner Fehler durch falsche EIngabe Allgemeine Java-Themen 4
I OpenPDF (ehem. iText) will kein PDF mit CMYK only erzeugen Allgemeine Java-Themen 6
A Kein Online-Zugang mögl.! Allgemeine Java-Themen 4
D kein Versand von Mails mit Anhang mehr Allgemeine Java-Themen 2
D Best Practice Gesamten Bildschirminhalt auslesen und Email schicken sobald kein Pixel sich ändert Allgemeine Java-Themen 11
R Warum kein throw? Allgemeine Java-Themen 3
W String Parsen und auf eigenes Muster anwenden (kein Regex) Allgemeine Java-Themen 11
A Datentypen Long.valueOf liefert kein "L" am Ende Allgemeine Java-Themen 3
B Input/Output Server Startet, Jedoch Kein Output. Allgemeine Java-Themen 1
B NullPointerException - Aber kein Fehler im Code Allgemeine Java-Themen 4
Guybrush Threepwood Kein user.home unter Windows8 Allgemeine Java-Themen 7
127.0.0.1 SQL Exception, kein Driver Allgemeine Java-Themen 9
Z Concurrent Modification Exception - HashMap (kein remove) Allgemeine Java-Themen 4
S Schnell eine fortlaufende nummer erzeugen SQL, kein Primkey Allgemeine Java-Themen 8
P Mail wird nicht gesendet - Muss ich kein PW angeben ? Allgemeine Java-Themen 13
G RegEx kein Unterstrich Allgemeine Java-Themen 2
E kein doppelter Programmaufruf Allgemeine Java-Themen 3
reibi Workspace schon geöffnet (Kein Eclipse Thema) Allgemeine Java-Themen 14
H Bestimmten String mit Pattern und Matcher herauslesen => kein erfolg Allgemeine Java-Themen 9
Z Boolean Abfrage gibt kein Boolean zurück, aber warum? Allgemeine Java-Themen 6
T GregorianCalendar - kein Februar Allgemeine Java-Themen 6
0 kein Java unter Server 2008 ? Allgemeine Java-Themen 3
I kann JAVA kein Mathe? Allgemeine Java-Themen 10
F Threading oder kein Threading - das ist hier die Frage. Allgemeine Java-Themen 23
V FileWriter und Zahlen (Kein Problem, nur Verständnisfrage) Allgemeine Java-Themen 4
T Problem, warum macht der das so(finde kein titel.) Allgemeine Java-Themen 3
K Kein schließendes Tag bei leerem Element mit JDOM Allgemeine Java-Themen 8
D Ich ikann kein Java-Programm starten Allgemeine Java-Themen 10
B Ausführungsproblem: admin, kein admin Allgemeine Java-Themen 2
E Warum kein Import? Allgemeine Java-Themen 3
L Kein Ausführen möglich Allgemeine Java-Themen 3
A Kein finally ausführen trotz verlassen des try blocks? Allgemeine Java-Themen 14
egrath Anonyme Methode - warum hier kein Compilerfehler Allgemeine Java-Themen 2
D kann kein java installieren Allgemeine Java-Themen 2
S Kein Sound in Java Applets unter Win 9x Allgemeine Java-Themen 4
P kein sound bei freenet spielen Allgemeine Java-Themen 2
K Scanner.hasNext findet kein Ende Allgemeine Java-Themen 6
K Problem mit Vererbung - Kein wirklicher Nutzen. Allgemeine Java-Themen 10
Redfrettchen addAll verwendet kein Iterator? Allgemeine Java-Themen 8
P Eclipse: Kein Fehler beim Debuging aber beim normalen run Allgemeine Java-Themen 3
T Feststellen ob kein extra Thread läuft Allgemeine Java-Themen 10
U Versions-Konfusion: Ist long kein object? Allgemeine Java-Themen 3
M DOS-Shell kennt kein CP850!! Allgemeine Java-Themen 2
D Kein public Konstruktor Allgemeine Java-Themen 4
LucasGlockner Effizienter byte-Zugriff auf ein long[]-Array Allgemeine Java-Themen 8
W Klassen Zugriff auf ein Textfile aus allen Klassen. Allgemeine Java-Themen 2
izoards Zugriff auf gemeinsame Ressource (CSV-File) Allgemeine Java-Themen 3
S Java Zugriff auf Netzwerklaufwerk Allgemeine Java-Themen 1
sascha-sphw Java 9 module Zugriff auf eine resource einer anderen JAR Allgemeine Java-Themen 0
KeexZDeveoper Zugriff auf Methoden vom Server Allgemeine Java-Themen 7
O Zugriff auf mySQL ohne JDBC Allgemeine Java-Themen 3
P Element einer Liste wurde hinzugefügt, aber es gibt keinen Zugriff Allgemeine Java-Themen 2
B Maven Zugriff auf files aus einem kompilierten jar Allgemeine Java-Themen 15
S Zugriff auf jUnit Test Suite Runner-Instanzen innerhalb von Test Classes Allgemeine Java-Themen 7
W Zugriff auf Objektvariablen vs. Übergabe Allgemeine Java-Themen 3
J Zugriff auf erstellte Objekte einer Klasse von einer Klasse ausserhalb Allgemeine Java-Themen 3
Tommy Nightmare HTTP Zugriff auf Internetseite im Loginbereich Allgemeine Java-Themen 5
H Zugriff auf PHP Allgemeine Java-Themen 4
B DB-Zugriff einer Webanwendung funktioniert nicht mit Java 7 Allgemeine Java-Themen 2
M WebService - Zugriff auf Webservice Methode über Browser Allgemeine Java-Themen 1
O JNA Zugriff auf Funktion aus DLL Allgemeine Java-Themen 0
O Zugriff auf Windows Zertifikatstore Allgemeine Java-Themen 2
T Zugriff auf Datenbank Allgemeine Java-Themen 1
J Zugriff auf IMAP GMail Konto scheitert. Allgemeine Java-Themen 2
P Frontend- Zugriff auf WS- Backend Allgemeine Java-Themen 0
U Zugriff auf Datei sperren Allgemeine Java-Themen 5
N Best Practice Semi-Synchronized Zugriff Allgemeine Java-Themen 0
C Zugriff auf Event felder Allgemeine Java-Themen 0
M Threads synchroner Zugriff (add/delete/read) auf eine Liste Allgemeine Java-Themen 6
F Zugriff Verweigert bei Kopieroperation? Allgemeine Java-Themen 4
S Dynamischer Zugriff Allgemeine Java-Themen 4
Minonos Einem Programm Zugriff auf bestimmte Ordner geben Allgemeine Java-Themen 5
E Zugriff auf Dateien im Filesystem überwachen Allgemeine Java-Themen 5
H Programierstil: static - Zugriff vs. Staticzugriff Allgemeine Java-Themen 24
V Zugriff auf den Objekterzeuger? Allgemeine Java-Themen 4
M Zugriff zweier Threads auf diesselbe Methode Allgemeine Java-Themen 16
B Zugriff auf eine HashMap Allgemeine Java-Themen 4
B JApplet Zugriff auf Local Storage des Browser? Allgemeine Java-Themen 2
D Zugriff auf Array-Liste Allgemeine Java-Themen 19
M gleichzeitiger Zugriff auf eine Textdatei Allgemeine Java-Themen 6
B synchronisierter zugriff auf Objekt Allgemeine Java-Themen 6
nutellastulle Zugriff, Übergabe, Bearbeitung und Ausgabe von Jlist Allgemeine Java-Themen 6
U Große Liste von Strings mit indiziertem Zugriff Allgemeine Java-Themen 31
J XML Element Zugriff Allgemeine Java-Themen 4
P Daten kopieren mit nio - Zugriff verweigert Allgemeine Java-Themen 8
M Klassen Zugriff auf getMethode ohne Klasse zu erzeugen Allgemeine Java-Themen 6
A Input/Output Applet-Zugriff auf PHP-Schnittstelle (externer Server) Allgemeine Java-Themen 22
H Vererbung Abgeleitete Klassen und Zugriff Allgemeine Java-Themen 2
C Probleme mit dem Zugriff auf private Methode per reflection Allgemeine Java-Themen 2
J Zugriff auf Poker-Client Fenster Allgemeine Java-Themen 14
C Zugriff auf private Methode per reflection geht nicht mehr Allgemeine Java-Themen 3
S Zugriff auf innere Klasse Allgemeine Java-Themen 3
Sonecc Zugriff auf Class File einer anderen Jar während der Laufzeit Allgemeine Java-Themen 2

Ähnliche Java Themen

Neue Themen


Oben