1

我参考了另一篇 stackoverflow 文章“如何将指针映射到 JNA 中的结构数组”以提供以下代码来枚举 Windows 服务依赖项。

结构和函数声明:

static class SERVICE_STATUS extends Structure {
    public int dwServiceType;
    public int dwCurrentState;
    public int dwControlsAccepted;
    public int dwWin32ExitCode;
    public int dwServiceSpecificExitCode;
    public int dwCheckPoint;
    public int dwWaitHint;
    public SERVICE_STATUS(){}
}

static class ENUM_SERVICE_STATUS extends Structure {
    public ENUM_SERVICE_STATUS(){ }

    public WString lpServiceName;
    public WString lpDisplayName;
    SERVICE_STATUS serviceStatus;
}

boolean EnumDependentServicesW(Pointer hService, int serviceState, ENUM_SERVICE_STATUS serviceStatuses, int size, IntByReference bytesNeeded, IntByReference servicesReturned);

如果只有一个服务依赖项,则以下代码有效:

IntByReference bytesNeeded = new IntByReference();
IntByReference numberOfServices = new IntByReference();
Advapi32.ENUM_SERVICE_STATUS serviceStatus = new Advapi32.ENUM_SERVICE_STATUS();
Advapi32.ENUM_SERVICE_STATUS[] serviceStatuses = (Advapi32.ENUM_SERVICE_STATUS[]) serviceStatus.toArray(1);

if (!advapi32.EnumDependentServicesW(serviceHandle, Advapi32.SERVICE_ACTIVE, null, 0, bytesNeeded, numberOfServices)) {
    if (advapi32.EnumDependentServicesW (serviceHandle, Advapi32.SERVICE_ACTIVE, serviceStatuses[0], bytesNeeded.getValue(), bytesNeeded, numberOfServices)) {
        for(int i = numberOfServices.getValue() - 1; i >= 0; i--){
            logger.debug("Service Name: " + serviceStatuses[i].lpServiceName.toString());
    }
}

如果有 2 个服务依赖项,我会在 logger.debug 调用中获得 lpServiceName 的 NullPointerException:

IntByReference bytesNeeded = new IntByReference();
IntByReference numberOfServices = new IntByReference();
Advapi32.ENUM_SERVICE_STATUS serviceStatus = new Advapi32.ENUM_SERVICE_STATUS();
Advapi32.ENUM_SERVICE_STATUS[] serviceStatuses = (Advapi32.ENUM_SERVICE_STATUS[]) serviceStatus.toArray(2);

if (!advapi32.EnumDependentServicesW(serviceHandle, Advapi32.SERVICE_ACTIVE, null, 0, bytesNeeded, numberOfServices)) { 
    if (advapi32.EnumDependentServicesW (serviceHandle, Advapi32.SERVICE_ACTIVE, serviceStatuses[0], bytesNeeded.getValue(), bytesNeeded, numberOfServices)) {
        for(int i = numberOfServices.getValue() - 1; i >= 0; i--){
            logger.debug("Service Name: " + serviceStatuses[i].lpServiceName.toString());
    }
}

正如预期的那样,上面代码的 numberOfServices 值为 2。我试图传递结构数组而不是指针,因为我希望 JNA 进行内存同步。我应该如何传递/使用结构数组?

4

1 回答 1

0

根据文档EnumDependentServices_

lpServices [输出,可选]

指向 ENUM_SERVICE_STATUS 结构数组的指针,该结构接收数据库中每个依赖服务的名称和服务状态信息。缓冲区必须足够大以容纳结构以及其成员指向的字符串。

您几乎忽略了bytesNeeded. 您应该使用该bytesNeeded值来创建Memory所需大小的实例,然后使用该Memory实例来创建新ENUM_SERVICE_STATUS实例,而不是独立于所需缓冲区大小来创建结构。

于 2012-10-11T12:42:18.177 回答