以下java
程序调用{{1}}中的本机方法,如果用户按下某个键,则该方法应打印消息C
。但我无法看到消息,因为我按下了键。我还检查函数you pressed a key !
是否返回null但不是,它不返回null。
Java代码:
SetWindowsHookEx
} C代码:
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");
}
我看到的唯一输出是不是NullInside fucntion setWinHook!
问题出在哪里?
当我按下该键时,我应该怎么做才能让该程序返回信息。
我看到的唯一输出是:#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;
}*/
注意:
如果上述程序在某人的机器上运行,请提及。
输出图片:
我没有在按键上看到任何消息。程序只在10秒后退出而不显示消息。
答案 0 :(得分: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。
答案 1 :(得分:0)
查看Java Global(low level) Keyboard/Mouse Hook
我自己写了一个,但似乎有太多未知的细节(JNI,HOOKS,穿线问题等)
答案 2 :(得分: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
。
答案 3 :(得分:0)
HHOOK 变量需要在共享数据段内声明。 在这里查看它是如何完成的 - http://www.codeproject.com/Articles/5002/Mousey-Roll-Over-and-Park
答案 4 :(得分:0)
您需要GetMessage/PeekMessage
循环才能使键盘挂钩接收任何事件。有关Windows上键盘钩子的Java实现,请参阅JNA Keyboard Hook in Windows或在JNA项目中执行相同功能的贡献包(https://github.com/twall/jna/tree/master/contrib/w32keyhook)。