Freigeben über


DevCreateObjectQuery-Funktion (devquery.h)

Erstellt eine Geräteabfrage zum Abrufen von Eigenschaften basierend auf den angegebenen Abfrageparametern.

Syntax

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

Parameter

[in] ObjectType

Ein Wert aus der DEV_OBJECT_TYPE-Aufzählung, der den Objekttyp bestimmt, für den diese Abfrage ausgeführt werden soll.

[in] QueryFlags

Eine Kombination aus DEV_QUERY_FLAGS Werten, die mithilfe eines bitweisen OR-Vorgangs kombiniert werden.

[in] cRequestedProperties

Die Anzahl der DEVPROPCOMPKEY- Strukturen, die in pRequestedPropertiesbereitgestellt werden. Wenn DevQueryFlagAllProperties- angegeben ist, muss dies auf 0 festgelegt werden.

[in] pRequestedProperties

Stellt optional ein Array von DEVPROPCOMPKEY- Strukturen bereit, die die Eigenschaften angeben, die für Objekte im Resultset der Abfrage abgerufen werden sollen, wenn pCallback- aufgerufen wird, um die Abfrage über das Hinzufügen eines Objekts zu seinem Resultset zu benachrichtigen.
Wenn DevQueryFlagUpdateResults- in QueryFlags-angegeben wurde, wird die Abfrage benachrichtigt, wenn sich der Wert dieser Eigenschaften für ein Objekt im Resultset der Abfrage ändert.

Das LocaleName- Feld der DEVPROPCOMPKEY- Struktur wird ignoriert und muss auf NULL festgelegt werden.

Wenn cRequestedProperties 0 ist, muss dies NULL sein.

[in] cFilterExpressionCount

Die Anzahl der in pFilterbereitgestellten DEVPROP_FILTER_EXPRESSION Strukturen.

[in, optional] pFilter

Stellt optional ein Array von DEVPROP_FILTER_EXPRESSION Strukturen bereit, die Filterkriterien für die Objekte angeben, die Teil des Resultsets der Abfrage sein sollen. Wenn cFilterExpressionCount 0 ist, muss dies NULL sein.

[in] pCallback

Eine PDEV_QUERY_RESULT_CALLBACK Rückruffunktion, an die Ergebnisse für diese Abfrage gesendet werden sollen.

[in, optional] pContext

Vom Aufrufer bereitgestellter Kontext. Dieser Wert wird an die Rückruffunktion übergeben, die nicht geändert wurde.

[out] phDevQuery

Zeiger, der das Handle empfängt, das die Abfrage darstellt. Wenn DevQueryFlagsUpdateResults- angegeben ist, empfängt die Abfrage Updates, bis das Handle geschlossen ist. Rufen Sie DevCloseObjectQuery auf, um dieses Handle zu schließen, um die Abfrage zu beenden.

Rückgabewert

S_OK wird zurückgegeben, wenn eine Abfrage erfolgreich erstellt wurde; andernfalls ein entsprechender Fehlerwert.

Bemerkungen

Verwenden Sie die DevCreateObjectQuery-, um Daten über die angegebene DEV_OBJECT_TYPEabzufragen. Objekte werden durch einen Objekttyp, eine Zeichenfolgenidentität und einen Eigenschaftenspeicher von Schlüssel-/Wertpaaren dargestellt. Jeder Abfrage ist ein Resultset zugeordnet. Objekte werden dem Resultset basierend auf Systemstatus und Änderungen hinzugefügt, aktualisiert oder aus dem Resultset entfernt, und die zugehörige Rückruffunktion wird benachrichtigt. Jeder Aufruf der Rückruffunktion stellt eine Momentaufnahme der Eigenschaftswerte zum Zeitpunkt des Aufrufs des Rückrufs dar. Nur Objekte, die den in der pFilter- Ausdruck ausgedrückten Kriterien entsprechen, werden an den Aufrufer zurückgegeben. Zusätzlich zu Rückrufaufrufen, die das Resultset aktualisieren, gibt es auch Statusänderungsrückrufe, die den Client über Änderungen am Status der Abfrage benachrichtigen.

Standardmäßig erhalten Abfragen keine Updates, nachdem der aktuelle Status des Systems verarbeitet wurde. Sobald alle übereinstimmenden Objekte dem Resultset hinzugefügt wurden, gibt die Abfrage den DevQueryStateEnumCompleted Zustand ein, und es werden keine weiteren Rückrufe vorgenommen. Wenn eine Abfrage für Updates registriert wird, indem die DevQueryFlagUpdateResults Flag angegeben wird, wird das Resultset weiterhin aktualisiert und der zugehörige Rückruf benachrichtigt, nachdem die Abfrage die DevQueryStateEnumCompleted Status eingegeben hat, wenn Änderungen im System auftreten, die Objekte basierend auf dem Abgleich des Filterausdrucks hinzufügen oder entfernen.

Eine Abfrage kann abgebrochen werden. Dies geschieht, wenn ein interner Fehler auftritt, der es unmöglich macht, eine Benachrichtigung an den Client zu kommunizieren. Dies kann beispielsweise passieren, wenn sich das System in einem Zustand außerhalb des Arbeitsspeichers befindet. In diesem Fall spiegelt das Resultset des Aufrufers keine echte Darstellung des Status der Abfrage mehr wider. Der Aufrufer empfängt einen DevQueryStateAborted Rückruf. Es werden keine weiteren Rückrufe empfangen. Der Aufrufer muss die Abfrage schließen und eine neue Abfrage erstellen, um diese Bedingung wiederherzustellen.

Beispiele

Im folgenden Beispiel wird die PDEV_QUERY_RESULT_CALLBACK-Methode implementiert, um Statusmeldungen auszudrucken, wenn sich der Abfragestatus ändert, wenn Elemente dem Abfrageergebnis hinzugefügt, aktualisiert oder daraus entfernt wurden. Als Nächstes wird ein einfaches Abfrageszenario implementiert, in dem DevCreateObjectQuery- mit einem DEVPROPCOMPKEY- array und einem DEVPROP_FILTER_EXPRESSION aufgerufen wird, um DevObjectTypeDevice Objekte mit einer DEVPKEY_Device_ClassGuid-Eigenschaft mit dem Wert GUID_DEVCLASS_NETabzufragen.

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

Im folgenden Beispiel wird der optionale aufruferdefinierte pContext Parameter verwendet, um ein Ereignishandle an die PDEV_QUERY_RESULT_CALLBACK-Methode zu übergeben. Wenn der Rückruf erkennt, dass der Abfragestatus DevQueryStateAbortedist, wird das Ereignis signalisiert, den Aufrufer darüber zu benachrichtigen, dass er die vorhandene Abfrage verwerfen und eine neue Abfrage neu erstellen soll.

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

Anforderungen

Anforderung Wert
mindestens unterstützte Client- Windows 10, Version 1809
mindestens unterstützte Server- Windows Server 2019
Header- devquery.h
Library onecore.lib
DLL- Cfgmgr32.dll

Siehe auch

DevCreateObjectQueryEx-