java 通过 jna/jni 调用 Hook 失败
java call Hook by jna/ jni failed
我需要全局禁用鼠标和键盘输入,但使用纯 java 无法解决问题。
我选择了jni/jna调用c++函数。当我通过jna调用c++函数时,java程序没有任何效果,没有任何错误或异常。
我已经测试了.dll文件,在c++中它不能运行完美。
这是我的 java 代码:
public class HookTest {
public interface Hook extends Library{
Hook INSTANCE = (Hook) Native.loadLibrary("lib/Hook",Hook.class);
public void FuncEndHook();
public void FuncHookDevice();
}
public static void main(String[] args) {
Hook.INSTANCE.FuncHookDevice();
}
}
我的 C++ 代码:
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include "stdio.h"
HHOOK g_HookHwnd = NULL;
HHOOK g_hMouse = NULL;
// 钩子子程
extern "C" _declspec(dllexport) LRESULT CALLBACK MyHookFun(int nCode, WPARAM wParam, LPARAM lParam)
{
printf("in hook key function\n");
// 这个Structure包含了键盘的信息
/*typedef struct {
DWORD vkCode;
DWORD scanCode;
DWORD flags;
DWORD time;
ULONG_PTR dwExtraInfo;
} KBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT;*/
// 我们只需要那个vkCode
PKBDLLHOOKSTRUCT pVirKey = (PKBDLLHOOKSTRUCT)lParam;
// MSDN说了,nCode < 0的时候别处理
if (nCode >= 0)
{
// 按键消息
switch (wParam)
{
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
case WM_KEYUP:
case WM_SYSKEYUP:
switch (pVirKey->vkCode)
{
case VK_LWIN:
case VK_RWIN:
return 1; // 吃掉消息
break;
}
return 1;
break;
}
}
return CallNextHookEx(g_HookHwnd, nCode, wParam, lParam);
}
extern "C" _declspec(dllexport) LRESULT CALLBACK MyHookMouse(int nCode, WPARAM wParam, LPARAM lParam)
{
printf("in hook mouse function\n");
return 1;
}
HMODULE g_Module;
extern "C" _declspec(dllexport) BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
{
break;
}
}
return TRUE;
}
extern "C" _declspec(dllexport) void FuncHookDevice()
{
if (!g_HookHwnd)
{
printf("start hook\n");
g_HookHwnd = SetWindowsHookEx(WH_KEYBOARD_LL, MyHookFun, g_Module, 0);
//g_hMouse = SetWindowsHookEx(WH_MOUSE_LL, MyHookMouse, g_Module, 0); //暂时禁用鼠标钩子
}
}
extern "C" _declspec(dllexport) void FuncEndHook()
{
printf("end hook\n");
UnhookWindowsHookEx(g_HookHwnd);
//UnhookWindowsHookEx(g_hMouse); //暂时禁用鼠标钩子
g_HookHwnd = NULL;
}
运行宁结果:
程序执行了c++,但没有禁用键盘。
感谢阅读和帮助。
看看LowLevelKeyboardProc
回调函数的备注部分是怎么说的:
This hook is called in the context of the thread that installed it. The call is made by sending a message to the thread that installed the hook. Therefore, the thread that installed the hook must have a message loop.
您已经为事件创建了一个挂钩,但是没有消息循环 处理这些事件。所有使用事件的 Windows 应用程序,例如使用本机 Windows 样式的图形桌面应用程序,都有一个消息循环调用 GetMessage
来获取事件并采取相应的行动。
您可以手动调用 WinAPI 函数来处理消息循环(GetMessage
、DispatchMessage
等),但我很高兴地说 JNA 确实有这个.
的帮手
在 jna-platform
包中(您需要将其添加到您的 Maven/Gradle/whatever 依赖项中),有一个名为 User32Util.MessageLoopThread
.
的 class
以下示例适用于我:
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.platform.win32.User32Util.MessageLoopThread;
public class HookTest {
public interface Hook extends Library {
Hook INSTANCE = (Hook) Native.loadLibrary("lib/Hook", Hook.class);
public void FuncEndHook();
public void FuncHookDevice();
}
public static void main(String[] args) {
MessageLoopThread thread = new MessageLoopThread();
thread.start();
thread.runOnThread(() -> {
Hook.INSTANCE.FuncHookDevice();
return null;
});
}
}
请注意,根据备注的要求,我在与消息循环相同的线程上显式调用了 FuncHookDevice
。
我需要全局禁用鼠标和键盘输入,但使用纯 java 无法解决问题。
我选择了jni/jna调用c++函数。当我通过jna调用c++函数时,java程序没有任何效果,没有任何错误或异常。
我已经测试了.dll文件,在c++中它不能运行完美。
这是我的 java 代码:
public class HookTest {
public interface Hook extends Library{
Hook INSTANCE = (Hook) Native.loadLibrary("lib/Hook",Hook.class);
public void FuncEndHook();
public void FuncHookDevice();
}
public static void main(String[] args) {
Hook.INSTANCE.FuncHookDevice();
}
}
我的 C++ 代码:
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include "stdio.h"
HHOOK g_HookHwnd = NULL;
HHOOK g_hMouse = NULL;
// 钩子子程
extern "C" _declspec(dllexport) LRESULT CALLBACK MyHookFun(int nCode, WPARAM wParam, LPARAM lParam)
{
printf("in hook key function\n");
// 这个Structure包含了键盘的信息
/*typedef struct {
DWORD vkCode;
DWORD scanCode;
DWORD flags;
DWORD time;
ULONG_PTR dwExtraInfo;
} KBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT;*/
// 我们只需要那个vkCode
PKBDLLHOOKSTRUCT pVirKey = (PKBDLLHOOKSTRUCT)lParam;
// MSDN说了,nCode < 0的时候别处理
if (nCode >= 0)
{
// 按键消息
switch (wParam)
{
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
case WM_KEYUP:
case WM_SYSKEYUP:
switch (pVirKey->vkCode)
{
case VK_LWIN:
case VK_RWIN:
return 1; // 吃掉消息
break;
}
return 1;
break;
}
}
return CallNextHookEx(g_HookHwnd, nCode, wParam, lParam);
}
extern "C" _declspec(dllexport) LRESULT CALLBACK MyHookMouse(int nCode, WPARAM wParam, LPARAM lParam)
{
printf("in hook mouse function\n");
return 1;
}
HMODULE g_Module;
extern "C" _declspec(dllexport) BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
{
break;
}
}
return TRUE;
}
extern "C" _declspec(dllexport) void FuncHookDevice()
{
if (!g_HookHwnd)
{
printf("start hook\n");
g_HookHwnd = SetWindowsHookEx(WH_KEYBOARD_LL, MyHookFun, g_Module, 0);
//g_hMouse = SetWindowsHookEx(WH_MOUSE_LL, MyHookMouse, g_Module, 0); //暂时禁用鼠标钩子
}
}
extern "C" _declspec(dllexport) void FuncEndHook()
{
printf("end hook\n");
UnhookWindowsHookEx(g_HookHwnd);
//UnhookWindowsHookEx(g_hMouse); //暂时禁用鼠标钩子
g_HookHwnd = NULL;
}
运行宁结果:
程序执行了c++,但没有禁用键盘。
感谢阅读和帮助。
看看LowLevelKeyboardProc
回调函数的备注部分是怎么说的:
This hook is called in the context of the thread that installed it. The call is made by sending a message to the thread that installed the hook. Therefore, the thread that installed the hook must have a message loop.
您已经为事件创建了一个挂钩,但是没有消息循环 处理这些事件。所有使用事件的 Windows 应用程序,例如使用本机 Windows 样式的图形桌面应用程序,都有一个消息循环调用 GetMessage
来获取事件并采取相应的行动。
您可以手动调用 WinAPI 函数来处理消息循环(GetMessage
、DispatchMessage
等),但我很高兴地说 JNA 确实有这个.
在 jna-platform
包中(您需要将其添加到您的 Maven/Gradle/whatever 依赖项中),有一个名为 User32Util.MessageLoopThread
.
以下示例适用于我:
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.platform.win32.User32Util.MessageLoopThread;
public class HookTest {
public interface Hook extends Library {
Hook INSTANCE = (Hook) Native.loadLibrary("lib/Hook", Hook.class);
public void FuncEndHook();
public void FuncHookDevice();
}
public static void main(String[] args) {
MessageLoopThread thread = new MessageLoopThread();
thread.start();
thread.runOnThread(() -> {
Hook.INSTANCE.FuncHookDevice();
return null;
});
}
}
请注意,根据备注的要求,我在与消息循环相同的线程上显式调用了 FuncHookDevice
。