0

以下java程序调用本机方法,如果用户按下某个键,C该方法应打印一条消息。you pressed a key !但是当我按下键时我看不到消息。我还检查函数是否SetWindowsHookEx返回 null 但不,它不返回 null。

Java 代码:

package keylogger;

public class TestKeys {

private native void setWinHook();

public static void main(String args[]) {
    TestKeys o = new TestKeys();
    try {
        o.setWinHook();
        Thread.sleep(10000);
    } catch(Exception exc) {
        exc.printStackTrace();
    }
}

static {
    System.loadLibrary("MyHook");
}

} C 代码:

#include <stdio.h>
#include <windows.h>
#include <w32api.h>
#include "keylogger_TestKeys.h"
static HHOOK handleKeyboardHook = NULL;
HINSTANCE hInst = NULL;

static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
  printf("You pressed a key !\n");
  return CallNextHookEx(handleKeyboardHook, nCode, wParam, lParam);
}

void Java_keylogger_TestKeys_setWinHook
 (JNIEnv *env, jobject obj) {
hInst = GetModuleHandle(NULL); // include or exclude,i don't see the result
handleKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc,NULL, 0);
if(handleKeyboardHook==NULL) {
    printf("Is Null");
} else {
    printf("Is not Null");
}
printf("Inside fucntion setWinHook !");
}

/*int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
 printf("Hello World !");
 handleKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hInstance, 0);
 if(handleKeyboardHook==NULL) {
  printf("Is Null");
 } else {
    printf("Is not Null");
   }
 MSG msg;
 while(GetMessage(&msg, NULL, 0, 0))
 {
   TranslateMessage(&msg);
   DispatchMessage(&msg);
 }
 return msg.wParam;
}*/

我看到的唯一输出是Is not NullInside fucntion setWinHook !

哪里有问题 ?

我应该怎么做才能让这个程序在我按下键时返回消息。我看到的唯一输出是:Inside function setWinHook !

笔记 :

如果上述程序在某人的机器上运行,请提及。

输出图片:

在此处输入图像描述

我在按键时没有看到任何消息。程序在 10 秒后退出而不显示消息。

4

5 回答 5

3

您不能简单地突然声明一个本地 HINSTANCE 变量并将其传递给函数。HINSTANCE 是应用程序实例的句柄,换句话说,它是必须指向有效位置的指针。您需要使用自己的应用程序 HINSTANCE。

我的 Windows API 有点生疏,但我相信您可以通过 GetModuleHandle() 来做到这一点。所以:

void Java_keylogger_TestKeys_setWinHook
     (JNIEnv *env, jobject obj) {
   HINSTANCE hInst;
   hInst = GetModuleHandle(null);
   handleKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hInst, 0);
   printf("Inside function setWinHook !");
 }

您的 Java goo 也很可能在某个对象中隐藏了 HINSTANCE。

于 2012-05-24T07:59:36.280 回答
0

查看Java 全局(低级)键盘/鼠标挂钩

我尝试自己写一个,但对我来说似乎有太多未知的细节(JNI、HOOKS、线程问题等)

于 2012-05-24T07:28:15.187 回答
0

肯定有更好的方法来实现这一点。一旦创建了一个线程,就会多次调用这里DllMain,这对我来说似乎不对。我不确定这是否合法!C 代码启动一个新线程来实现 keycatcher。

C代码:

#include <stdio.h>
#include <windows.h>
#include <w32api.h>
#include "keylogger_TestKeys.h"

static HHOOK handleKeyboardHook = NULL;
HINSTANCE hInst = NULL;
static DWORD hookThreadId = 0;
static HANDLE hookThreadHandle = NULL;
BOOL WINAPI installHook(HINSTANCE hinstDLL, DWORD fwdReason, LPVOID lpvReserved);
static int i = 0;

static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {

  printf("You pressed the key !");
  return CallNextHookEx(handleKeyboardHook, nCode, wParam, lParam);
}


BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
 if(hookThreadHandle==NULL) {
    printf("hookThreadHandle is NULL\n");
    LPTHREAD_START_ROUTINE lpStartAddress = &installHook;
    hookThreadHandle = CreateThread(NULL, 0, lpStartAddress, NULL, 0, &hookThreadId);
 }
}

BOOL WINAPI installHook(HINSTANCE hinstDLL, DWORD fwdReason, LPVOID lpvReserved) {
// printf("From installHook : %u",fwdReason);
printf("count : %d\n",i++);
handleKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hinstDLL, 0);
MSG msg;

while(GetMessage(&msg, NULL, 0, 0))
{
  TranslateMessage(&msg);
  DispatchMessage(&msg);
}
return msg.wParam;
}

void Java_keylogger_TestKeys_unregisterWinHook
 (JNIEnv *env, jobject obj) {
 // should have stopped the thread before unhooking
 if(handleKeyboardHook != NULL) {
    UnhookWindowsHookEx(handleKeyboardHook);
 }
}

void Java_keylogger_TestKeys_stopNativeThread // stop the native thread
  (JNIEnv *env, jobject obj) {
    PostThreadMessage(hookThreadId, WM_QUIT, (WPARAM) NULL, (LPARAM) NULL);
    WaitForSingleObject(hookThreadHandle, 5000);
}

Java 代码:

package keylogger;

public class TestKeys {
private static int i = 0;
private native void setWinHook();
private native void unregisterWinHook();
private native void createWinThread();
private native void stopNativeThread();

public static void main(String args[]) {
    TestKeys o = new TestKeys();
    try {
        Thread.sleep(5000);
    }catch(Exception exc) {
        exc.printStackTrace();
    }
   o.stopNativeThread();
   o.unregisterWinHook();
   System.out.println("Native thread stopped and Hook unregistered !");

   try {
        Thread.sleep(3000); // Now you won't see the message : you pressed the key 
    }catch(Exception exc) {
        exc.printStackTrace();
    }
}

static {
    System.loadLibrary("MyHook");
}
}

我启动java程序并被DLLMain调用。

于 2012-05-30T05:46:57.853 回答
0

HHOOK变量需要在共享数据段内声明在这里检查它是如何完成的 - http://www.codeproject.com/Articles/5002/Mousey-Roll-Over-and-Park

于 2012-05-30T06:15:50.107 回答
0

您需要一个GetMessage/PeekMessage循环才能让您的键盘挂钩接收任何事件。有关 Windows 上键盘挂钩的 Java 实现,请参阅Windows 中的 JNA 键盘挂钩,或在 JNA 项目中执行相同功能的贡献包 ( https://github.com/twall/jna/tree/master/contrib/ w32keyhook)。

于 2012-05-31T00:25:24.380 回答