使用JNA获取服务列表

时间:2019-02-26 09:48:33

标签: java winapi jna

我需要列出(STATE = ALL)已安装,正在运行和已停止的所有服务。之前我使用命令“ sc query”,但我需要使用JNA来执行此操作。我以前从未使用过JNA,所以我并不了解。

我找到了这个Query all Windows Services with JNA,并做了回答,但我无法正常工作。

public void getService(){
    IntByReference size = new IntByReference();
    IntByReference lppcbBytesneeded = new IntByReference();
    IntByReference retz = new IntByReference();
    lppcbBytesneeded.setValue(0);
    Winsvc.SC_HANDLE scm = Advapi32.INSTANCE.OpenSCManager(null, null, Winsvc.SC_MANAGER_ENUMERATE_SERVICE);
    boolean ret = CustomAdvapi32.INSTANCE.EnumServicesStatusEx(scm.getPointer(), 0, 0x00000030, 0x0000003, null, 0, lppcbBytesneeded,
            retz, size, null);
    int error = Native.getLastError();

    Memory buf = new Memory(lppcbBytesneeded.getValue());
    size.setValue(retz.getValue());
    ret = CustomAdvapi32.INSTANCE.EnumServicesStatusEx(scm.getPointer(), 0, 0x00000030, 0x0000000,
            buf, lppcbBytesneeded.getValue(), lppcbBytesneeded, retz, size, null);
    error = Native.getLastError();


    ENUM_SERVICE_STATUS_PROCESS serviceInfo = new ENUM_SERVICE_STATUS_PROCESS(buf);
    Structure[] serviceInfos = serviceInfo.toArray(retz.getValue());

    for(int i = 0; i < retz.getValue(); i++) {
        serviceInfo = (ENUM_SERVICE_STATUS_PROCESS) serviceInfos[i];
        System.out.println(serviceInfo.lpDisplayName + " / " + serviceInfo.lpServiceName);
    }
}

我所能得到的就是错误:

java.lang.ArrayIndexOutOfBoundsException: 0
at com.sun.jna.Structure.toArray(Structure.java:1562)
at com.sun.jna.Structure.toArray(Structure.java:1587)
at Main.getService(Main.java:156)
at Main.main(Main.java:22)

1 个答案:

答案 0 :(得分:0)

您的错误是在size.setValue(retz.getValue());中。当您第二次调用该方法时,您将size用作lpResumeHandle字段:

  

指向变量的指针,该变量在输入时指定起点   枚举。您必须在第一次设置时将此值设置为零。   调用EnumServicesStatusEx函数。输出时,该值为零   如果功能成功。但是,如果函数返回零,   GetLastError函数返回ERROR_MORE_DATA,此值   指示当   调用EnumServicesStatusEx函数以检索其他   数据。

因此,在第二个调用中,您要告诉JNA在上一个列表中的最后一个元素之后开始迭代。毫不奇怪,您得到retz.getValue()无法处理的空数组(Structure.toArray() == 0)。

您应该在将参数设置为0的情况下调用EnumServicesStatusEx,以便从头开始枚举。