サポートされているサービス メソッドの取得

サービス メソッドは、各サービスが定義して実装する機能をカプセル化します。 これらはサービスの種類ごとに固有であり、一意の GUID で表されます。

たとえば、Contacts サービスは、アプリケーションが Contact オブジェクトを同期するためにデバイスを準備するために呼び出す BeginSync メソッドと、同期が完了したことをデバイスに通知する EndSync メソッドを定義します。

アプリケーションでは、サポートされているメソッドにプログラムでクエリを実行し、 IPortableDeviceServiceCapabilities インターフェイスを使用してこれらのメソッドとその属性にアクセスできます。

サービス メソッドを WPD コマンドと混同しないでください。 WPD コマンドは、標準の WPD デバイス ドライバー インターフェイス (DDI) の一部であり、WPD アプリケーションとドライバー間の通信のメカニズムです。 コマンドは定義済みで、WPD_CATEGORY_COMMONなどのカテゴリ別にグループ化され、PROPERTYKEY 構造体で表されます。 詳細については、「 コマンド 」トピックを参照してください。

WpdServicesApiSample アプリケーションには、アプリケーションが次の表のインターフェイスを使用して、特定の Contacts サービスでサポートされているメソッドを取得する方法を示すコードが含まれています。

インターフェイス 説明
IPortableDeviceService サポートされているサービス メソッドにアクセスするための IPortableDeviceServiceCapabilities インターフェイスを取得するために使用します。
IPortableDeviceServiceCapabilities サポートされているメソッド、メソッド属性、およびメソッド パラメーターへのアクセスを提供します。
IPortableDevicePropVariantCollection サポートされているメソッドの一覧が含まれます。
IPortableDeviceValues メソッドおよび特定のメソッドのパラメーターの属性を格納します。
IPortableDeviceKeyCollection 特定のメソッドのパラメーターを格納します。

 

ユーザーがコマンド ラインでオプション "5" を選択すると、アプリケーションは ServiceMethods.cpp モジュールにある ListSupportedMethods メソッドを呼び出します。

イベントの一覧を取得する前に、サンプル アプリケーションは接続されているデバイスで連絡先サービスを開きます。

WPD では、メソッドは、その名前、アクセス権、パラメーター、および関連データによって記述されます。 サンプル アプリケーションには、わかりやすい名前 ("CustomMethod" や GUID など) が表示されます。 メソッド名または GUID の後にアクセス データ ("読み取り/書き込み")、関連付けられている形式の名前、およびパラメーター データが続きます。 このデータには、パラメーター名、使用法、VARTYPE、およびフォームが含まれます。

ServiceMethods.cpp モジュールの 5 つのメソッドは、指定された連絡先サービスのメソッド (および関連データ) の取得をサポートしています。 ListSupportedMethodsDisplayMethodDisplayMethodAccessDisplayFormatおよび DisplayMethodParametersListSupportedMethods メソッドは、サポートされているメソッドの数と、それぞれの GUID 識別子を取得します。次に、DisplayMethod メソッドを呼び出します。 DisplayMethod メソッドは、IPortableDeviceServiceCapapbilities::GetMethodAttributes メソッドを呼び出して、指定されたメソッドのオプションやパラメーターなどを取得します。 DisplayMethod は、メソッド データを取得した後、名前 (または GUID)、アクセス制限、関連付けられている形式 (存在する場合)、およびパラメーターの説明をレンダリングします。 DisplayMethodAccessDisplayFormat、および DisplayMethodParameters は、それぞれのデータ フィールドをレンダリングするヘルパー関数です。

ListSupportedMethods メソッドは、IPortableDeviceService::Capabilities メソッドを呼び出して IPortableDeviceServiceCapabilities インターフェイスを取得します。 このインターフェイスを使用して、 IPortableDeviceServiceCapabilities::GetSupportedMethods メソッドを呼び出して、サポートされているメソッドを取得します。 GetSupportedMethods メソッドは、サービスでサポートされている各メソッドの GUID を取得し、その GUID を IPortableDevicePropVariantCollection オブジェクトにコピーします。

次のコードでは、 ListSupportedMethods メソッドを使用します

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

ListSupportedMethods メソッドは、指定されたサービスでサポートされている各イベントの GUID を取得した後、DisplayMethod メソッドを呼び出してメソッド固有の属性を取得します。 これらの属性には、メソッドのスクリプトフレンドリ名、必要なアクセス制限、関連付けられている形式、パラメーターの一覧が含まれます。

DisplayMethod メソッドは、IPortableDeviceServiceCapabilities::GetMethodAttributes メソッドを呼び出して、指定されたメソッドの属性のコレクションを取得します。 その後、 IPortableDeviceValues::GetStringValue メソッドを呼び出して、メソッドの名前を取得します。 DisplayMethodIPortableDeviceValues::GetUnsignedIntegerValue を呼び出して、アクセスの restrctions を取得します。 その後、 IPortableDeviceValues::GetGuidValue を呼び出して、関連付けられている形式を取得します。 最後に、 DisplayMethodIPortableDeviceValues::GetIPortableDeviceKeyCollectionValue を呼び出してパラメーター データを取得します。 これらのメソッドによって返されたデータは、指定されたメソッドの情報をレンダリングする DisplayMethodAccessDisplayFormat、および DisplayMethodParameters ヘルパー関数に渡されます。

次のコードでは、 DisplayMethod メソッドを使用します。

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

    }
}

DisplayMethodAccess ヘルパー関数は、メソッドのアクセス オプションを含む DWORD 値を受け取ります。 この値をWPD_COMMAND_ACCESS_READと比較し、WPD_COMMAND_ACCESS_READWRITEしてメソッドのアクセス特権を決定します。 結果を使用して、指定されたメソッドのアクセス制限を示す文字列をレンダリングします。

次のコードでは、 DisplayMethodAccess ヘルパー関数を使用します。

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

DisplayMethod ヘルパー関数は、IPortableDeviceServiceCapabilities オブジェクトとメソッドの GUID をパラメーターとして受け取ります。 IPortableDeviceServiceCapabilities オブジェクトを使用して、IPortableDeviceServiceCapabilities::GetMethodAttributes メソッドを呼び出してメソッド属性を取得し、アプリケーションのコンソール ウィンドウにレンダリングします。

DisplayMethodParameters ヘルパー関数は、IPortableDeviceServiceCapabilities オブジェクト、メソッドの GUID、およびメソッド パラメーターを含む IPortableDeviceKeyCollection オブジェクトを受け取ります。 IPortableDeviceKeyCollection オブジェクトを使用して、IPortableDeviceServiceCapabilities::GetMethodParameterAttributes メソッドを呼び出して、パラメーターの名前、使用法、VARTYPE、およびフォームを取得します。 この情報は、アプリケーションのコンソール ウィンドウにレンダリングされます。

次のコードでは、 DisplayMethodParameters ヘルパー関数を使用します。

// 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