java通过jaboc调用dll(大漠插件)遇到的坑,变参指针传参问题

刚接触java调用动态链接库,这几天踩了不少坑。先记录下来方便以后学习,也希望可以帮助到有需要的同志。由于第一次写博客,如果写的不好或者不详细请各位大神嘴下留情,多多包涵! 首先说下背景,我本人是魔兽世界忠实玩家,偶尔写下游戏脚本。去年一直使用按键精灵,大概使用了打半年也没有没检测到。今年突然一下被封了3个账号,按键精灵(个人版普通用户)试过各种办法,隐藏进程、加壳貌似都没有用。可能我技术太菜了吧!别问我为啥不开VIP,我会告诉你我很穷吗?最近发现魔兽会检测按键精灵进程(先启动游戏再启动按键结果一样),万般无奈只好另谋出路。偶然得知java原来也可以调用dll,然后就尝试的去玩一下。接下来等待我的是一个又一个坑等着我去跳,网上关于这块资料讲的不够细,导致花费了大量时间。今天写这篇文章也是希望能帮助正在爬坑的人。接下来进入正题,通过各种途径了解到java调用dll有那么几种方法:最底层的JNI、最方便的JNA、Jawin、.jacob、Jnative。在这里就不一 一说了。在这里给个建议吧!从使用方便角度来讲,java调用标准dll建议使用JNA,为什么说标准的dll呢?那是因为有些生成的dll并不是标准的,比如我正在使用的VB写的大漠插件(dm.dll)。com组件的话就使用jacob,没得说,一会我直接上码就知道了。首先说下我遇到的问题,以大漠获取鼠标位置为例(其他类型的下面链接可以找到例子)

java通过jaboc调用dll(大漠插件)遇到的坑,变参指针传参问题java通过jaboc调用dll(大漠插件)遇到的坑,变参指针传参问题

一、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