1

Windows サービスの依存関係を列挙する次のコードを作成するために、別のスタック オーバーフローの記事「JNA でポインターを構造体の配列にマップする方法」を参照しました。

構造体と関数の宣言:

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);

サービスの依存関係が 1 つしかない場合は、次のコードが機能します。

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 [out、オプション]

データベース内の各依存サービスの名前とサービスステータス情報を受け取るENUM_SERVICE_STATUS構造体の配列へのポインター。バッファは、構造体とそのメンバーが指す文字列を保持するのに十分な大きさである必要があります。

によって報告されているように、必要なバッファサイズをほとんど無視していますbytesNeeded。必要なバッファサイズに関係なく構造を作成するのではなく、bytesNeeded値を使用しMemoryて必要なサイズのインスタンスを作成してから、そのMemoryインスタンスを使用して新しいインスタンスを作成する必要があります。ENUM_SERVICE_STATUS

于 2012-10-11T12:42:18.177 に答える