Freigeben über


Abrufen unterstützter Dienstmethoden

Dienstmethoden kapseln funktionen, die jeder Dienst definiert und implementiert. Sie sind für jeden Diensttyp spezifisch und werden durch eine eindeutige GUID dargestellt.

Der Contacts-Dienst definiert beispielsweise eine BeginSync-Methode , die Anwendungen aufrufen, um das Gerät für die Synchronisierung von Contact-Objekten vorzubereiten, und eine EndSync-Methode , um das Gerät über den Abschluss der Synchronisierung zu benachrichtigen.

Anwendungen können die unterstützten Methoden programmgesteuert abfragen und mithilfe der IPortableDeviceServiceCapabilities-Schnittstelle auf diese Methoden und ihre Attribute zugreifen.

Dienstmethoden sollten nicht mit WPD-Befehlen verwechselt werden. WPD-Befehle sind Teil der standardmäßigen WPD Device Driver Interface (DDI) und der Mechanismus für die Kommunikation zwischen einer WPD-Anwendung und dem Treiber. Befehle sind vordefiniert, nach Kategorien gruppiert, z. B. WPD_CATEGORY_COMMON, und werden durch eine PROPERTYKEY-Struktur dargestellt. Weitere Informationen finden Sie im Thema Befehle .

Die WpdServicesApiSample-Anwendung enthält Code, der veranschaulicht, wie eine Anwendung die von einem bestimmten Contacts-Dienst unterstützten Methoden mithilfe der Schnittstellen in der folgenden Tabelle abrufen kann.

Schnittstelle Beschreibung
IPortableDeviceService Wird verwendet, um die IPortableDeviceServiceCapabilities-Schnittstelle für den Zugriff auf die unterstützten Dienstmethoden abzurufen.
IPortableDeviceServiceCapabilities Bietet Zugriff auf die unterstützten Methoden, Methodenattribute und Methodenparameter.
IPortableDevicePropVariantCollection Enthält die Liste der unterstützten Methoden.
IPortableDeviceValues Enthält die Attribute für eine Methode und für die Parameter einer bestimmten Methode.
IPortableDeviceKeyCollection Enthält die Parameter für eine bestimmte Methode.

 

Wenn der Benutzer die Option "5" in der Befehlszeile auswähelt, ruft die Anwendung die ListSupportedMethods-Methode auf, die sich im Modul ServiceMethods.cpp befindet.

Beachten Sie, dass die Beispielanwendung vor dem Abrufen der Ereignisliste einen Kontaktdienst auf einem verbundenen Gerät öffnet.

In WPD wird eine Methode durch ihren Namen, zugriffsrechte, Parameter und zugehörige Daten beschrieben. Die Beispielanwendung zeigt einen benutzerfreundlichen Namen an, z. B. "CustomMethod" oder eine GUID. Auf den Methodennamen oder die GUID folgen Zugriffsdaten ("Lesen/Schreiben"), der Name eines beliebigen zugeordneten Formats und die Parameterdaten. Diese Daten umfassen den Parameternamen, die Verwendung, VARTYPE und das Formular.

Fünf Methoden im Modul ServiceMethods.cpp unterstützen das Abrufen von Methoden (und zugehörigen Daten) für den angegebenen Kontaktdienst: ListSupportedMethods, DisplayMethod, DisplayMethodAccess, DisplayFormat und DisplayMethodParameters. Die ListSupportedMethods-Methode ruft die Anzahl der unterstützten Methoden und den GUID-Bezeichner für jede methode ab. Anschließend wird die DisplayMethod-Methode aufgerufen. Die DisplayMethod-Methode ruft die IPortableDeviceServiceCapapbilities::GetMethodAttributes-Methode auf, um die Optionen, Parameter usw. der angegebenen Methode abzurufen. Nachdem displayMethod die Methodendaten abgerufen hat, rendert sie den Namen (oder die GUID), die Zugriffsbeschränkungen, das zugeordnete Format (falls vorhanden) und die Parameterbeschreibungen. DisplayMethodAccess, DisplayFormat und DisplayMethodParameters sind Hilfsfunktionen, die ihre jeweiligen Datenfelder rendern.

Die ListSupportedMethods-Methode ruft die IPortableDeviceService::Capabilities-Methode auf, um eine IPortableDeviceServiceCapabilities-Schnittstelle abzurufen. Mithilfe dieser Schnittstelle werden die unterstützten Methoden abgerufen, indem die IPortableDeviceServiceCapabilities::GetSupportedMethods-Methode aufgerufen wird. Die GetSupportedMethods-Methode ruft die GUIDs für jede vom Dienst unterstützte Methode ab und kopiert diese GUID in ein IPortableDevicePropVariantCollection-Objekt .

Der folgende Code verwendet die ListSupportedMethods-Methode .

// List all supported methods on the service
void ListSupportedMethods(IPortableDeviceService* pService)
{
    HRESULT hr              = S_OK;
    DWORD   dwNumMethods    = 0;
    CComPtr<IPortableDeviceServiceCapabilities>     pCapabilities;
    CComPtr<IPortableDevicePropVariantCollection>   pMethods;

    if (pService == NULL)
    {
        printf("! A NULL IPortableDeviceService interface pointer was received\n");
        return;
    }

    // Get an IPortableDeviceServiceCapabilities interface from the IPortableDeviceService interface to
    // access the service capabilities-specific methods.
    hr = pService->Capabilities(&pCapabilities);
    if (FAILED(hr))
    {
        printf("! Failed to get IPortableDeviceServiceCapabilities from IPortableDeviceService, hr = 0x%lx\n",hr);
    }

    // Get all methods supported by the service.
    if (SUCCEEDED(hr))
    {
        hr = pCapabilities->GetSupportedMethods(&pMethods);
        if (FAILED(hr))
        {
            printf("! Failed to get supported methods from the service, hr = 0x%lx\n",hr);
        }
    }

    // Get the number of supported methods found on the service.
    if (SUCCEEDED(hr))
    {
        hr = pMethods->GetCount(&dwNumMethods);
        if (FAILED(hr))
        {
            printf("! Failed to get number of supported methods, hr = 0x%lx\n",hr);
        }
    }

    printf("\n%d Supported Methods Found on the service\n\n", dwNumMethods);

    // Loop through each method and display it
    if (SUCCEEDED(hr))
    {
        for (DWORD dwIndex = 0; dwIndex < dwNumMethods; dwIndex++)
        {
            PROPVARIANT pv = {0};
            PropVariantInit(&pv);
            hr = pMethods->GetAt(dwIndex, &pv);

            if (SUCCEEDED(hr))
            {
                // We have a method.  It is assumed that
                // methods are returned as VT_CLSID VarTypes.
                if (pv.puuid != NULL)
                {
                    DisplayMethod(pCapabilities, *pv.puuid);
                    printf("\n");
                }
            }

            PropVariantClear(&pv);
        }
    }    
}

Nachdem die ListSupportedMethods-Methode die GUID für jedes ereignis abgerufen hat, das vom angegebenen Dienst unterstützt wird, ruft sie die DisplayMethod-Methode auf, um die methodenspezifischen Attribute abzurufen. Zu diesen Attributen gehören: der skriptfreundliche Name der Methode, erforderliche Zugriffsbeschränkungen, jedes zugeordnete Format und eine Liste von Parametern.

Die DisplayMethod-Methode ruft die IPortableDeviceServiceCapabilities::GetMethodAttributes-Methode auf, um eine Auflistung von Attributen für die angegebene Methode abzurufen. Anschließend wird die IPortableDeviceValues::GetStringValue-Methode aufgerufen, um den Namen der Methode abzurufen. Die DisplayMethod ruft IPortableDeviceValues::GetUnsignedIntegerValue auf, um die Zugriffsrestrctions abzurufen. Danach wird IPortableDeviceValues::GetGuidValue aufgerufen, um ein beliebiges zugeordnetes Format abzurufen. Und schließlich ruft die DisplayMethodIPortableDeviceValues::GetIPortableDeviceKeyCollectionValue auf, um die Parameterdaten abzurufen. Die von diesen Methoden zurückgegebenen Daten werden an die Hilfsfunktionen DisplayMethodAccess, DisplayFormat und DisplayMethodParameters übergeben, die die Informationen für die angegebene Methode rendern.

Der folgende Code verwendet die DisplayMethod-Methode .

// Display basic information about a method
void DisplayMethod(
    IPortableDeviceServiceCapabilities* pCapabilities,
    REFGUID                             Method)
{
    CComPtr<IPortableDeviceValues> pAttributes;

    // Get the method attributes which describe the method
    HRESULT hr = pCapabilities->GetMethodAttributes(Method, &pAttributes);
    if (FAILED(hr))
    {
        printf("! Failed to get the method attributes, hr = 0x%lx\n",hr);
    }

    if (SUCCEEDED(hr))
    {
        PWSTR   pszMethodName  = NULL;
        DWORD   dwMethodAccess = WPD_COMMAND_ACCESS_READ;
        GUID    guidFormat     = GUID_NULL;

        CComPtr<IPortableDeviceValues>          pOptions;
        CComPtr<IPortableDeviceKeyCollection>   pParameters;

        // Display the name of the method if available. Otherwise, fall back to displaying the GUID.
        hr = pAttributes->GetStringValue(WPD_METHOD_ATTRIBUTE_NAME, &pszMethodName);
        if (SUCCEEDED(hr))
        {
            printf("%ws", pszMethodName);
        }
        else
        {
            printf("%ws", (PWSTR)CGuidToString(Method));
        }       

        // Display the method access if available, otherwise default to WPD_COMMAND_ACCESS_READ access
        hr = pAttributes->GetUnsignedIntegerValue(WPD_METHOD_ATTRIBUTE_ACCESS, &dwMethodAccess);
        if (FAILED(hr))
        {
            dwMethodAccess = WPD_COMMAND_ACCESS_READ;
            hr = S_OK;
        }
        printf("\n\tAccess: ");
        DisplayMethodAccess(dwMethodAccess);

        // Display the associated format if specified.
        // Methods that have an associated format may only be supported for that format.
        // Methods that don't have associated formats generally apply to the entire service.
        hr = pAttributes->GetGuidValue(WPD_METHOD_ATTRIBUTE_ASSOCIATED_FORMAT, &guidFormat);
        if (SUCCEEDED(hr))
        {
            printf("\n\tAssociated Format: ");
            DisplayFormat(pCapabilities, guidFormat);
        }

        // Display the method parameters, if available
        hr = pAttributes->GetIPortableDeviceKeyCollectionValue(WPD_METHOD_ATTRIBUTE_PARAMETERS, &pParameters);
        if (SUCCEEDED(hr))
        {
            DisplayMethodParameters(pCapabilities, Method, pParameters);
        }
        
        CoTaskMemFree(pszMethodName);
        pszMethodName = NULL;

    }
}

Die Hilfsfunktion DisplayMethodAccess empfängt einen DWORD-Wert, der die Zugriffsoptionen der Methode enthält. Dieser Wert wird mit WPD_COMMAND_ACCESS_READ und WPD_COMMAND_ACCESS_READWRITE verglichen, um die Zugriffsberechtigungen der Methode zu bestimmen. Mithilfe des Ergebnisses wird eine Zeichenfolge gerendert, die die Zugriffsbeschränkung für die angegebene Methode angibt.

Im folgenden Code wird die Hilfsfunktion DisplayMethodAccess verwendet.

void DisplayMethodAccess(
    DWORD   dwAccess)
{
    switch(static_cast<WPD_COMMAND_ACCESS_TYPES>(dwAccess))
    {
        case WPD_COMMAND_ACCESS_READ:
            printf("Read");
            break;
            
        case WPD_COMMAND_ACCESS_READWRITE:
            printf("Read/Write");
            break;

        default:
            printf("Unknown Access");
            break;
    }
}

Die DisplayMethod-Hilfsfunktion empfängt ein IPortableDeviceServiceCapabilities-Objekt und die GUID der Methode als Parameter. Mithilfe des IPortableDeviceServiceCapabilities-Objekts wird die IPortableDeviceServiceCapabilities::GetMethodAttributes-Methode aufgerufen, um die Methodenattribute abzurufen und im Konsolenfenster der Anwendung zu rendern.

Die Hilfsfunktion DisplayMethodParameters empfängt ein IPortableDeviceServiceCapabilities-Objekt , die GUID der Methode und ein IPortableDeviceKeyCollection-Objekt, das die Methodenparameter enthält. Mithilfe des IPortableDeviceKeyCollection-Objekts wird die IPortableDeviceServiceCapabilities::GetMethodParameterAttributes-Methode aufgerufen, um den Namen, die Verwendung, den VARTYPE und das Formular des Parameters abzurufen. Diese Informationen werden im Konsolenfenster der Anwendung gerendert.

Im folgenden Code wird die Hilfsfunktion DisplayMethodParameters verwendet.

// Display the method parameters.
void DisplayMethodParameters(
    IPortableDeviceServiceCapabilities* pCapabilities,
    REFGUID                             Method,
    IPortableDeviceKeyCollection*       pParameters)
{
    DWORD   dwNumParameters = 0;

    // Get the number of parameters for this event.
    HRESULT hr = pParameters->GetCount(&dwNumParameters);
    if (FAILED(hr))
    {
        printf("! Failed to get number of parameters, hr = 0x%lx\n",hr);
    }

    printf("\n\t%d Method Parameters:\n", dwNumParameters);

    // Loop through each parameter and display it
    if (SUCCEEDED(hr))
    {
        for (DWORD dwIndex = 0; dwIndex < dwNumParameters; dwIndex++)
        {
            PROPERTYKEY parameter;
            hr = pParameters->GetAt(dwIndex, &parameter);

            if (SUCCEEDED(hr))
            {
                CComPtr<IPortableDeviceValues> pAttributes;

                // Display the parameter's Name, Usage, Vartype, and Form
                hr = pCapabilities->GetMethodParameterAttributes(Method, parameter, &pAttributes);
                if (FAILED(hr))
                {
                    printf("! Failed to get the method parameter attributes, hr = 0x%lx\n",hr);
                }

                if (SUCCEEDED(hr))
                {
                    PWSTR   pszParameterName    = NULL;
                    DWORD   dwAttributeVarType  = 0;
                    DWORD   dwAttributeForm     = WPD_PARAMETER_ATTRIBUTE_FORM_UNSPECIFIED;
                    DWORD   dwAttributeUsage    = (DWORD)-1;

                    hr = pAttributes->GetStringValue(WPD_PARAMETER_ATTRIBUTE_NAME, &pszParameterName);
                    if (SUCCEEDED(hr))
                    {
                        printf("\t\tName: %ws\n", pszParameterName);
                    }
                    else
                    {
                        printf("! Failed to get the method parameter name, hr = 0x%lx\n",hr);
                    }

                    // Read the WPD_PARAMETER_ATTRIBUTE_USAGE value, if specified. 
                    hr = pAttributes->GetUnsignedIntegerValue(WPD_PARAMETER_ATTRIBUTE_USAGE, &dwAttributeUsage);
                    if (SUCCEEDED(hr))
                    {
                        printf("\t\tUsage: ");
                        DisplayParameterUsage(dwAttributeUsage);
                        printf("\n");
                    }
                    else
                    {
                        printf("! Failed to get the method parameter usage, hr = 0x%lx\n",hr);
                    }

                    hr = pAttributes->GetUnsignedIntegerValue(WPD_PARAMETER_ATTRIBUTE_VARTYPE, &dwAttributeVarType);
                    if (SUCCEEDED(hr))
                    {
                        printf("\t\tVARTYPE: ");
                        DisplayVarType(static_cast<VARTYPE>(dwAttributeVarType));
                        printf("\n");
                    }
                    else
                    {
                        printf("! Failed to get the method parameter VARTYPE, hr = 0x%lx\n",hr);
                    }

                    // Read the WPD_PARAMETER_ATTRIBUTE_FORM value.
                    hr = pAttributes->GetUnsignedIntegerValue(WPD_PARAMETER_ATTRIBUTE_FORM, &dwAttributeForm);
                    if (FAILED(hr))
                    {
                        // If the read fails, assume WPD_PARAMETER_ATTRIBUTE_FORM_UNSPECIFIED
                        dwAttributeForm = WPD_PARAMETER_ATTRIBUTE_FORM_UNSPECIFIED;
                        hr = S_OK;
                    }

                    printf("\t\tForm: ");
                    DisplayParameterForm(dwAttributeForm);
                    printf("\n");

                    CoTaskMemFree(pszParameterName);
                    pszParameterName = NULL;
                }
                
                printf("\n");
            }
        }
    }
}

IPortableDeviceKeyCollection

IPortableDeviceService

IPortableDeviceServiceCapabilities

IPortableDeviceValues

WpdServicesApiSample