次の方法で共有


DevCreateObjectQuery 関数 (devquery.h)

指定したクエリ パラメーターに基づいてプロパティを取得するデバイス クエリを作成します。

構文

HRESULT DevCreateObjectQuery(
  [in]           DEV_OBJECT_TYPE                 ObjectType,
  [in]           ULONG                           QueryFlags,
  [in]           ULONG                           cRequestedProperties,
  [in]           const DEVPROPCOMPKEY            *pRequestedProperties,
  [in]           ULONG                           cFilterExpressionCount,
  [in, optional] const DEVPROP_FILTER_EXPRESSION *pFilter,
  [in]           PDEV_QUERY_RESULT_CALLBACK      pCallback,
  [in, optional] PVOID                           pContext,
  [out]          PHDEVQUERY                      phDevQuery
);

パラメーター

[in] ObjectType

このクエリが操作する必要があるオブジェクトの種類を決定する DEV_OBJECT_TYPE 列挙体の値。

[in] QueryFlags

ビットごとの OR 演算を使用して結合される DEV_QUERY_FLAGS 値の組み合わせ。

[in] cRequestedProperties

pRequestedPropertiesで提供される DEVPROPCOMPKEY 構造体の数。 DevQueryFlagAllProperties 指定する場合は、0 に設定する必要があります。

[in] pRequestedProperties

必要に応じて、pCallback 呼び出されたときにクエリの結果セット内のオブジェクトに対して取得するプロパティを指定する DEVPROPCOMPKEY 構造体の配列を提供 、結果セットへのオブジェクトの追加をクエリに通知します。
QueryFlags
で DevQueryFlagUpdateResults が指定された場合、クエリの結果セット内のオブジェクトに対してこれらのプロパティの値が変更された場合、クエリに通知されます。

DEVPROPCOMPKEY 構造体の LocaleName フィールドは無視され、NULL に設定する必要があります。

cRequestedProperties が 0 の場合、これは NULL である必要があります。

[in] cFilterExpressionCount

pFilterで提供される DEVPROP_FILTER_EXPRESSION 構造体の数。

[in, optional] pFilter

必要に応じて、クエリの結果セットに含めるオブジェクトのフィルター条件を指定する DEVPROP_FILTER_EXPRESSION 構造体の配列を提供します。 cFilterExpressionCount が 0 の場合、これは NULL である必要があります。

[in] pCallback

このクエリの結果を送信する必要がある PDEV_QUERY_RESULT_CALLBACK コールバック関数。

[in, optional] pContext

呼び出し元が指定したコンテキスト。 この値は、変更されていないコールバック関数に渡されます。

[out] phDevQuery

クエリを表すハンドルを受け取るポインター。 devQueryFlagsUpdateResults 指定した場合、クエリはハンドルが閉じられるまで更新を受け取ります。 DevCloseObjectQuery 呼び出して、このハンドルを閉じてクエリを停止します。

戻り値

クエリが正常に作成された場合、S_OKが返されます。それ以外の場合は、適切なエラー値。

備考

DevCreateObjectQuery を使用して、指定した DEV_OBJECT_TYPEに関するデータを照会します。 オブジェクトは、オブジェクト型、文字列 ID、およびキーと値のペアのプロパティ ストアによって表されます。 各クエリには、結果セットが関連付けられています。 オブジェクトは、システムの状態と変更に基づいて結果セットに追加、更新、または削除され、関連付けられているコールバック関数に通知されます。 コールバック関数の各呼び出しは、コールバックが呼び出されたときにプロパティ値のスナップショットを表します。 pFilter 式で表された条件に一致するオブジェクトのみが呼び出し元に返されます。 結果セットを更新するコールバック呼び出しに加えて、クエリの状態に対する変更をクライアントに通知する状態変更コールバックもあります。

既定では、システムの現在の状態が処理された後、クエリは更新プログラムを受信しません。 一致するすべてのオブジェクトが結果セットに追加されると、クエリは devQueryStateEnumCompleted 状態になり、それ以上のコールバックは行われません。 DevQueryFlagUpdateResults フラグを指定してクエリが更新プログラムに登録されると、その結果セットは引き続き更新され、関連付けられたコールバックが通知されます。クエリは、フィルター式の一致に基づいてオブジェクトを追加または削除するシステムの変更が発生したときに、DevQueryStateEnumCompleted 状態に入ります。

クエリが中止される可能性があります。 これは、内部エラーが発生し、クライアントに通知を伝えることができない場合に発生します。 たとえば、これは、システムがメモリ不足状態にある場合に発生する可能性があります。 この場合、呼び出し元の結果セットは、クエリの状態の真の表現を反映しなくなります。 呼び出し元は、DevQueryStateAborted コールバックを受け取ります。 それ以上のコールバックは受信されません。 呼び出し元は、クエリを閉じ、この条件から復旧するための新しいクエリを作成する必要があります。

次の例では、PDEV_QUERY_RESULT_CALLBACK メソッドを実装して、クエリの状態が変更されたとき、項目がクエリ結果に追加、更新、または削除されたときに、ステータス メッセージを出力します。 次に、DevCreateObjectQueryDEVPROPCOMPKEY 配列で呼び出し、値が GUID_DEVCLASS_NETDEVPKEY_Device_ClassGuid プロパティを持つ DevObjectTypeDevice オブジェクト 対してクエリを実行する DEVPROP_FILTER_EXPRESSION を実装する単純なクエリ シナリオを実装します。

void WINAPI
Example1Callback(
    HDEVQUERY hDevQuery,
    PVOID pContext,
    const DEV_QUERY_RESULT_ACTION_DATA *pActionData
    )
{
    const DEVPROPERTY* NameProperty = NULL;

    UNREFERENCED_PARAMETER(hDevQuery);
    UNREFERENCED_PARAMETER(pContext);

    switch (pActionData->Action)
    {
    case DevQueryResultStateChange:
        if (pActionData->Data.State == DevQueryStateEnumCompleted)
        {
            wprintf(L"Enumeration of current system state complete.\n");
        }
        else if (pActionData->Data.State == DevQueryStateAborted)
        {
            wprintf(L"Query has aborted. No further results will be received.\n");
            // Communicate back to the creator of the query that it has aborted
            // so it can handle that appropriately, such as by recreating the
            // query
        }
        break;

    case DevQueryResultAdd:
        wprintf(L"Object '%ws' has been added to the result set.\n",
                pActionData->Data.DeviceObject.pszObjectId);

        NameProperty = DevFindProperty(&DEVPKEY_NAME,
                                       DEVPROP_STORE_SYSTEM,
                                       NULL,
                                       pActionData->Data.DeviceObject.cPropertyCount,
                                       pActionData->Data.DeviceObject.pProperties);

        if ((NameProperty == NULL) ||
            (NameProperty->Type == DEVPROP_TYPE_EMPTY) ||
            (NameProperty->Buffer == NULL))
        {
            wprintf(L"Object '%ws' had no name property.\n",
                    pActionData->Data.DeviceObject.pszObjectId);
        }
        else if ((NameProperty->Type != DEVPROP_TYPE_STRING) ||
                 (NameProperty->BufferSize < sizeof(WCHAR)))
        {
            wprintf(L"Object '%ws' had a corrupted name property.\n",
                    pActionData->Data.DeviceObject.pszObjectId);
        }
        else
        {
            wprintf(L"Object '%ws' has name '%ws'.\n",
                    pActionData->Data.DeviceObject.pszObjectId,
                    (PWSTR)NameProperty->Buffer);
        }

        break;

    case DevQueryResultUpdate:
        wprintf(L"Object '%ws' was updated.\n",
                pActionData->Data.DeviceObject.pszObjectId);

        NameProperty = DevFindProperty(&DEVPKEY_NAME,
                                       DEVPROP_STORE_SYSTEM,
                                       NULL,
                                       pActionData->Data.DeviceObject.cPropertyCount,
                                       pActionData->Data.DeviceObject.pProperties);

        if ((NameProperty == NULL) ||
            (NameProperty->Type == DEVPROP_TYPE_EMPTY) ||
            (NameProperty->Buffer == NULL))
        {
            wprintf(L"Object '%ws' had no name property.\n",
                    pActionData->Data.DeviceObject.pszObjectId);
        }
        else if ((NameProperty->Type != DEVPROP_TYPE_STRING) ||
                 (NameProperty->BufferSize < sizeof(WCHAR)))
        {
            wprintf(L"Object '%ws' had a corrupted name property.\n",
                    pActionData->Data.DeviceObject.pszObjectId);
        }
        else
        {
            wprintf(L"Object '%ws' has name '%ws'.\n",
                    pActionData->Data.DeviceObject.pszObjectId,
                    (PWSTR)NameProperty->Buffer);
        }

        break;

    case DevQueryResultRemove:
        wprintf(L"Object '%ws' has been removed from the result set.\n",
                pActionData->Data.DeviceObject.pszObjectId);
        break;
    }
}

void
Example1()
{
    DEVPROPCOMPKEY RequestedProperties[] =
    {
        { DEVPKEY_NAME, DEVPROP_STORE_SYSTEM, NULL }
    };
    DEVPROP_FILTER_EXPRESSION ObjectFilter[] =
    {
        {
            DEVPROP_OPERATOR_EQUALS,
            {
                { DEVPKEY_Device_ClassGuid, DEVPROP_STORE_SYSTEM, NULL },
                DEVPROP_TYPE_GUID,
                sizeof(GUID),
                (void*)&GUID_DEVCLASS_NET
            }
        }
    };

    HDEVQUERY hDevQuery = NULL;
    HRESULT hr = DevCreateObjectQuery(DevObjectTypeDevice,
                                      DevQueryFlagUpdateResults,
                                      RTL_NUMBER_OF(RequestedProperties),
                                      RequestedProperties,
                                      RTL_NUMBER_OF(ObjectFilter),
                                      ObjectFilter,
                                      Example1Callback,
                                      NULL,
                                      &hDevQuery);

    if (FAILED(hr))
    {
        wprintf(L"Failed to create query. hr = 0x%08x\n", hr);
        goto exit;
    }

    // do other work while the query monitors system state in the background

  exit:

    if (hDevQuery != NULL)
    {
        DevCloseObjectQuery(hDevQuery);
    }

    return;
}

次の例では、オプションの呼び出し元定義 pContext パラメーターを使用して、イベント ハンドルを PDEV_QUERY_RESULT_CALLBACK メソッドに渡します。 クエリ状態が DevQueryStateAbortedであることがコールバックによって検出されると、既存のクエリを破棄して新しいクエリを再作成する必要があることを呼び出し元に通知するイベントが通知されます。

typedef struct _MY_QUERY_CONTEXT {
    HANDLE CompletionEvent;
    HRESULT hr;
} MY_QUERY_CONTEXT, *PMY_QUERY_CONTEXT;

void WINAPI
Example2Callback(
    HDEVQUERY hDevQuery,
    PVOID pContext,
    const DEV_QUERY_RESULT_ACTION_DATA *pActionData
    )
{
    PMY_QUERY_CONTEXT QueryContext = (PMY_QUERY_CONTEXT)pContext;
    const DEVPROPERTY* DevProperty = NULL;

    UNREFERENCED_PARAMETER(hDevQuery);

    switch (pActionData->Action)
    {
    case DevQueryResultStateChange:
        if (pActionData->Data.State == DevQueryStateEnumCompleted)
        {
            wprintf(L"Enumeration of current system state complete.\n");
            // The query did not use DevQueryFlagUpdateResults so the result set
            // is now complete. Signal the caller to stop waiting.
            if (!SetEvent(QueryContext->CompletionEvent))
            {
                wprintf(L"Failed to signal completion event. Err = 0x%08x\n",
                        GetLastError());
            }
        }
        else if (pActionData->Data.State == DevQueryStateAborted)
        {
            wprintf(L"Query has aborted. No further results will be received.\n");
            QueryContext->hr = E_FAIL;
            // Communicate back to the creator of the query that it has aborted
            // so it can handle that appropriately, such as by recreating the
            // query.
            if (!SetEvent(QueryContext->CompletionEvent))
            {
                wprintf(L"Failed to signal completion event. Err = 0x%08x\n",
                        GetLastError());
            }
        }
        break;

    case DevQueryResultAdd:
        wprintf(L"Object '%ws' has been added to the result set.\n",
                pActionData->Data.DeviceObject.pszObjectId);

        DevProperty = DevFindProperty(&DEVPKEY_Device_InstanceId,
                                      DEVPROP_STORE_SYSTEM,
                                      NULL,
                                      pActionData->Data.DeviceObject.cPropertyCount,
                                      pActionData->Data.DeviceObject.pProperties);

        if ((DevProperty == NULL) ||
            (DevProperty->Type == DEVPROP_TYPE_EMPTY) ||
            (DevProperty->Buffer == NULL))
        {
            wprintf(L"Object '%ws' had no instance ID property.\n",
                    pActionData->Data.DeviceObject.pszObjectId);
        }
        else if ((DevProperty->Type != DEVPROP_TYPE_STRING) ||
                 (DevProperty->BufferSize < sizeof(WCHAR)))
        {
            wprintf(L"Object '%ws' had a corrupted instance ID property.\n",
                    pActionData->Data.DeviceObject.pszObjectId);
        }
        else
        {
            wprintf(L"Object '%ws' was exposed by instance ID '%ws'.\n",
                    pActionData->Data.DeviceObject.pszObjectId,
                    (PWSTR)DevProperty->Buffer);
        }

        break;

    case DevQueryResultUpdate:
        wprintf(L"Object '%ws' was updated.\n",
                pActionData->Data.DeviceObject.pszObjectId);

        DevProperty = DevFindProperty(&DEVPKEY_Device_InstanceId,
                                      DEVPROP_STORE_SYSTEM,
                                      NULL,
                                      pActionData->Data.DeviceObject.cPropertyCount,
                                      pActionData->Data.DeviceObject.pProperties);

        if ((DevProperty == NULL) ||
            (DevProperty->Type == DEVPROP_TYPE_EMPTY) ||
            (DevProperty->Buffer == NULL))
        {
            wprintf(L"Object '%ws' had no instance ID property.\n",
                    pActionData->Data.DeviceObject.pszObjectId);
        }
        else if ((DevProperty->Type != DEVPROP_TYPE_STRING) ||
                 (DevProperty->BufferSize < sizeof(WCHAR)))
        {
            wprintf(L"Object '%ws' had a corrupted instance ID property.\n",
                    pActionData->Data.DeviceObject.pszObjectId);
        }
        else
        {
            wprintf(L"Object '%ws' was exposed by instance ID '%ws'.\n",
                    pActionData->Data.DeviceObject.pszObjectId,
                    (PWSTR)DevProperty->Buffer);
        }

        break;

    case DevQueryResultRemove:
        wprintf(L"Object '%ws' has been removed from the result set.\n",
                pActionData->Data.DeviceObject.pszObjectId);
        break;
    }
}

void
Example2()
{
    HRESULT hr = S_OK;
    MY_QUERY_CONTEXT QueryContext = {0};
    HDEVQUERY hDevQuery = NULL;
    DEVPROP_BOOLEAN DevPropTrue = DEVPROP_TRUE;
    DEVPROPCOMPKEY RequestedProperties[] =
    {
        { DEVPKEY_Device_InstanceId, DEVPROP_STORE_SYSTEM, NULL }
    };
    DEVPROP_FILTER_EXPRESSION ObjectFilter[] =
    {
        {
            DEVPROP_OPERATOR_AND_OPEN, {0}
        },
        {
            DEVPROP_OPERATOR_EQUALS,
            {
                { DEVPKEY_DeviceInterface_Enabled, DEVPROP_STORE_SYSTEM, NULL },
                DEVPROP_TYPE_BOOLEAN,
                sizeof(DevPropTrue),
                (void*)&DevPropTrue
            }
        },
        {
            DEVPROP_OPERATOR_OR_OPEN, {0}
        },
        {
            DEVPROP_OPERATOR_EQUALS,
            {
                { DEVPKEY_DeviceInterface_ClassGuid, DEVPROP_STORE_SYSTEM, NULL },
                DEVPROP_TYPE_GUID,
                sizeof(GUID),
                (void*)&GUID_DEVINTERFACE_MOUSE
            }
        },
        {
            DEVPROP_OPERATOR_EQUALS,
            {
                { DEVPKEY_DeviceInterface_ClassGuid, DEVPROP_STORE_SYSTEM, NULL },
                DEVPROP_TYPE_GUID,
                sizeof(GUID),
                (void*)&GUID_DEVINTERFACE_KEYBOARD
            }
        },
        {
            DEVPROP_OPERATOR_OR_CLOSE, {0}
        },
        {
            DEVPROP_OPERATOR_AND_CLOSE, {0}
        }
    };

    QueryContext.CompletionEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

    if (!QueryContext.CompletionEvent)
    {
        wprintf(L"Failed to create event. Error = 0x%08x\n",
                GetLastError());
        goto exit;
    }

    hr = DevCreateObjectQuery(DevObjectTypeDeviceInterface,
                              DevQueryFlagNone,
                              RTL_NUMBER_OF(RequestedProperties),
                              RequestedProperties,
                              RTL_NUMBER_OF(ObjectFilter),
                              ObjectFilter,
                              Example2Callback,
                              &QueryContext,
                              &hDevQuery);

    if (FAILED(hr))
    {
        wprintf(L"Failed to create query. hr = 0x%08x\n", hr);
        goto exit;
    }

    switch (WaitForSingleObject(QueryContext.CompletionEvent, INFINITE))
    {
    case WAIT_OBJECT_0:
        if (SUCCEEDED(QueryContext.hr))
        {
            wprintf(L"Successfully enumerated results.\n");
        }
        else
        {
            wprintf(L"Failed to Successfully enumerate results. hr = 0x%08x\n",
                    QueryContext.hr);
        }
        break;

    default:
        wprintf(L"An error waiting occurred.\n");
        break;
    }

  exit:

    if (hDevQuery != NULL)
    {
        DevCloseObjectQuery(hDevQuery);
    }

    if (QueryContext.CompletionEvent != NULL)
    {
        CloseHandle(QueryContext.CompletionEvent);
    }

    return;
}

必要条件

要件 価値
サポートされる最小クライアント Windows 10 バージョン 1809
サポートされる最小サーバー Windows Server 2019
ヘッダー devquery.h
ライブラリ onecore.lib
DLL Cfgmgr32.dll

関連項目

DevCreateObjectQueryEx の