刚接触java调用动态链接库,这几天踩了不少坑。先记录下来方便以后学习,也希望可以帮助到有需要的同志。由于第一次写博客,如果写的不好或者不详细请各位大神嘴下留情,多多包涵! 首先说下背景,我本人是魔兽世界忠实玩家,偶尔写下游戏脚本。去年一直使用按键精灵,大概使用了打半年也没有没检测到。今年突然一下被封了3个账号,按键精灵(个人版普通用户)试过各种办法,隐藏进程、加壳貌似都没有用。可能我技术太菜了吧!别问我为啥不开VIP,我会告诉你我很穷吗?最近发现魔兽会检测按键精灵进程(先启动游戏再启动按键结果一样),万般无奈只好另谋出路。偶然得知java原来也可以调用dll,然后就尝试的去玩一下。接下来等待我的是一个又一个坑等着我去跳,网上关于这块资料讲的不够细,导致花费了大量时间。今天写这篇文章也是希望能帮助正在爬坑的人。接下来进入正题,通过各种途径了解到java调用dll有那么几种方法:最底层的JNI、最方便的JNA、Jawin、.jacob、Jnative。在这里就不一 一说了。在这里给个建议吧!从使用方便角度来讲,java调用标准dll建议使用JNA,为什么说标准的dll呢?那是因为有些生成的dll并不是标准的,比如我正在使用的VB写的大漠插件(dm.dll)。com组件的话就使用jacob,没得说,一会我直接上码就知道了。首先说下我遇到的问题,以大漠获取鼠标位置为例(其他类型的下面链接可以找到例子)
一、JNA 方式测试 GetMousePointWindow函数
public class DllTest {
public interface Dll extends StdCallLibrary {
Dll instance = (Dll) Native.loadLibrary("d:\\dm.dll", Dll.class);
long GetMousePointWindow();
}
public static void main(String[] args) {
System.out.println("sum = " + Dll.instance.GetMousePointWindow());
}
}
结果:
java.lang.UnsatisfiedLinkError: Error looking up function 'GetMousePointWindow': 找不到指定的程序。
二、JNA 方式测试 GetCursorPos函数 (由于我本人不会C/C++,指针传值问题让我很头疼)
public interface Dll extends StdCallLibrary { Dll instance = (Dll) Native.loadLibrary("d:\\dm.dll", Dll.class); Long GetCursorPos(Pointer x, Pointer y); } public static void main(String[] args) { Pointer x = new Memory(11) ; Pointer y = new Memory(11) ; Long result = Dll.instance.GetCursorPos(x, y); System.out.println("result = "+result); System.out.println("x = "+x); System.out.println("y = "+y); }
结果:
java.lang.UnsatisfiedLinkError: Error looking up function 'GetCursorPos': 找不到指定的程序
三、JACOB方式测试 GetMousePointWindow函数
ActiveXComponent ax = new ActiveXComponent("dm.dmsoft"); Variant variant = Dispatch.call(ax, "GetMousePointWindow"); System.out.println("variant = " + variant);
结果:
variant = 396170 搞定,正确得到句柄
四、JACOB方式测试 GetCursorPos 函数 (最严重的问题来了)
测试 1
ActiveXComponent ax = new ActiveXComponent("dm.dmsoft"); Pointer x = new Memory(11) ; Pointer y = new Memory(11) ; Variant variant = Dispatch.call(ax, "GetCursorPos",x,y); System.out.println("variant = " + variant); System.out.println("x = " + x); System.out.println("y = " + y);
结果:
com.jacob.com.NotImplementedException: populateVariant() not implemented for class com.sun.jna.Memory
测试 2
ActiveXComponent ax = new ActiveXComponent("dm.dmsoft"); try { Pointer x = new Pointer(MemoryBlockFactory.createMemoryBlock(4 * 10)); Pointer y = new Pointer(MemoryBlockFactory.createMemoryBlock(4 * 10)); Variant variant = Dispatch.call(ax, "GetCursorPos",x,y); System.out.println("variant = " + variant); System.out.println("x = " + x); System.out.println("y = " + y); } catch (NativeException e) { e.printStackTrace(); }
结果:
com.jacob.com.NotImplementedException: populateVariant() not implemented for class org.xvolks.jnative.pointers.Pointer
测试 3
ActiveXComponent ax = new ActiveXComponent("dm.dmsoft"); try { Variant[] var = new Variant[2]; Pointer x = new Memory(11) ; Pointer y = new Memory(11) ; //Pointer x = new Pointer(MemoryBlockFactory.createMemoryBlock(4 * 10)); //Pointer y = new Pointer(MemoryBlockFactory.createMemoryBlock(4 * 10)); var[0] = new Variant(x); var[1] = new Variant(y); Variant variant = Dispatch.call(ax, "GetCursorPos",var); System.out.println("variant = " + variant); System.out.println("x = " + x); System.out.println("y = " + y); } catch (NativeException e) { e.printStackTrace(); }
结果:
com.jacob.com.NotImplementedException: populateVariant() not implemented for class org.xvolks.jnative.pointers.Pointer
测试 4
ActiveXComponent ax = new ActiveXComponent("dm.dmsoft"); int x = 0, y = 0; Variant[] var = new Variant[2]; var[0] = new Variant(x,true); var[1] = new Variant(y,true); Variant variant = Dispatch.call(ax, "GetCursorPos",var); System.out.println("variant = " + variant); System.out.println("x = " + var[0]); System.out.println("y = " + var[1]);
结果:
variant = 1 x = 672 y = 463 终于搞定了,我的妈啊!
简单总结:
1、标准dll推荐JNA,使用简单方便(不考虑性能情况下)、对于没有C/C++基础的人来说JNA指针的处理相对复杂
2、COM组件、非标准DLL推荐JACOB,理由很简单,看测试4变参指针(红字)使用,纯java模式
3、相对复杂,并且JNA、JACOB无法实现的部分再考虑JNI
4、因为我不了解JNATIVE,所以在这我就不做评论
5、今天就这样吧!如果有发现我这边有啥问题欢迎指正,也欢迎留言相互学习
6、在啰嗦一句,有没有人有过游戏检测CE的(可以附加进程的),我这边的可以过游戏检测,但是附加不了进程。跪求
给两个链接吧
JNA 方式
https://www.cnblogs.com/new-life/p/9345840.html
JACOB 方式(这篇文章写的相对比较全,列举了不少大漠例子)
https://blog.csdn.net/qwkxq/article/details/53575627