Я пишу регистратор ключей JNI и собственный код для этого, как показано ниже.
#include "com_webspur_rmtadmin_java_app_keylogger_KeyloggerHelper.h"
#include "com_webspur_rmtadmin_java_app_keylogger_KeyloggerHelper_KeyListener.h"
#include <cstring>
#include <windows.h>
#include <iostream>
#include <stdio.h>
HINSTANCE hinst;
HHOOK hhk;
JNIEnv * thisEnv;
jclass thisClazz;
jmethodID mid;
LRESULT __declspec(dllexport)__stdcall CALLBACK KeyboardProc(int ,WPARAM , LPARAM );
BOOL WINAPI DllMain( __in HINSTANCE hinstDLL,
__in DWORD fdwReason,
__in LPVOID lpvReserved
) {
hinst = hinstDLL;
return TRUE;
}
LRESULT __declspec(dllexport)__stdcall CALLBACK KeyboardProc(int nCode,WPARAM wParam, LPARAM lParam){
thisEnv->CallStaticVoidMethod(thisClazz, mid, nCode);
LRESULT RetVal = CallNextHookEx( hhk, nCode, wParam, lParam );
return RetVal;
}
JNIEXPORT void JNICALL Java_com_webspur_rmtadmin_java_app_keylogger_KeyloggerHelper_unhookKeyListener
(JNIEnv * env, jclass clazz){
thisEnv = NULL;
thisClazz = NULL;
mid = NULL;
UnhookWindowsHookEx(hhk);
}
JNIEXPORT void JNICALL Java_com_webspur_rmtadmin_java_app_keylogger_KeyloggerHelper_hookKeyListener
(JNIEnv * env, jclass clazz){
thisEnv = env;
thisClazz = clazz;
mid = env->GetStaticMethodID( clazz, "onKeyPress", "(I)V");
hhk = SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyboardProc,hinst,0);
}
Цель программы - уведомить Java-программу (статический метод onKeyPress) из собственного кода, где яБуду регистрировать ключи и уведомлять пользователя.Сначала я вызову hookKeyListener (собственная версия: Java_com_webspur_rmtadmin_java_app_keylogger_KeyloggerHelper_hookKeyListener), где я зарегистрирую хук окон и сохраню все параметры (env, jclass и mid).В обратном вызове ( KeyboardProc ) я уведомлю java-программу, используя ранее сохраненные env , jClass , mid .и, наконец, отмените регистрацию хука.
Теперь проблема, с которой я сталкиваюсь, заключается в том, что Java-метод (статический) не вызывается из собственного кода. Ниже приведены некоторые мои наблюдения.
1> Если вызовJava-метод в Java_com_webspur_rmtadmin_java_app_keylogger_KeyloggerHelper_hookKeyListener, он успешно вызывает java-метод (это означает, что я могу вызывать статические методы)
2> Я написал некоторый тестовый код в KeyboardProc (CallBack), например, создаю файл и записываю в него ключи,работает хорошо (это означает, что Hook зарегистрирован правильно и также вызывается при нажатии клавиши)
Но я не могу вызвать код Java из CallBack (KeyboardProc). У меня есть сомнения по поводу хранимых переменных (env, jClass, mid) -можно ли сохранить эти параметры в глобальных переменных? Если нет, то как я могу вызвать программу Java из собственного кода? Любая помощь приветствуется.
Ниже приведен код Java, который я хочу вызывать из собственного кода..
package com.webspur.rmtadmin.java.app.keylogger;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.HashMap;
public class KeyloggerHelper {
static{
System.loadLibrary("KeyHookLibrary");
}
public interface KeyListener{
public void onKeyPress(int keyCode);
}
private static boolean started = false;
private static KeyListener keyListener = null;
private static BufferedWriter writer = null;
private static HashMap<Integer, String> specialKeys = new HashMap<Integer, String>();
public static void init(){
try{
File logFile = new File("./resources/leylog.txt");
if(!logFile.exists())
logFile.createNewFile();
writer = new BufferedWriter(new FileWriter(logFile, true));
}catch (Exception e) {
e.printStackTrace();
}
}
public static void start(KeyListener listener){
keyListener = listener;
if(!started)
startInternal();
}
public static void stop(){
keyListener = null;
if(started)
stopInternal();
}
private static void stopInternal() {
try{
unhookKeyListener();
started = false;
writer.close();
}catch (Exception e) {
e.printStackTrace();
}
}
private static native void unhookKeyListener();
private static void startInternal(){
hookKeyListener();
started = true;
}
private static native void hookKeyListener();
public static void onKeyPress(int keyCode){
try{
if(keyListener!=null)
keyListener.onKeyPress(keyCode);
writer.append((char)keyCode);
}catch (Exception e) {
//ignore..
}
}
}