共用方式為


擷取支援的服務方法

服務方法會封裝每個服務所定義和實作的功能。 它們專屬於每種服務類型,並以唯一 GUID 表示。

例如,Contacts 服務會定義 BeginSync 方法,讓應用程式呼叫以準備裝置以同步處理 Contact 物件,以及 EndSync 方法,以通知裝置同步處理已完成。

應用程式可以使用 IPortableDeviceServiceCapabilities 介面,以程式設計方式查詢支援的方法,並存取這些方法及其屬性。

服務方法不應與 WPD 命令混淆。 WPD 命令是標準 WPD 設備磁碟機介面 (DDI) 的一部分,而且是 WPD 應用程式和驅動程式之間通訊的機制。 命令是預先定義的、依類別分組,例如,WPD_CATEGORY_COMMON,並以 PROPERTYKEY 結構表示。 如需詳細資訊,請參閱 命令 主題。

WpdServicesApiSample 應用程式包含程式碼,示範應用程式如何使用下表中的介面來擷取指定連絡人服務支援的方法。

介面 描述
IPortableDeviceService 用來擷取 IPortableDeviceServiceCapabilities 介面來存取支援的服務方法。
IPortableDeviceServiceCapabilities 提供支援的方法、方法屬性和方法參數的存取權。
IPortableDevicePropVariantCollection 包含支援的方法清單。
IPortableDeviceValues 包含方法的屬性,以及指定方法的參數的屬性。
IPortableDeviceKeyCollection 包含指定方法的參數。

 

當使用者在命令列選擇選項 「5」 時,應用程式會叫用 ServiceMethods.cpp 模組中找到的 ListSupportedMethods 方法。

請注意,在擷取事件清單之前,範例應用程式會在連線的裝置上開啟連絡人服務。

在 WPD 中,方法會以其名稱、存取權限、參數和相關資料來描述。 範例應用程式會顯示使用者易記的名稱,例如 「CustomMethod」 或 GUID。 方法名稱或 GUID 後面接著存取資料 (「讀取/寫入」) 、任何相關聯格式的名稱,以及參數資料。 此資料包括參數名稱、使用方式、VARTYPE 和表單。

ServiceMethods.cpp 模組中的五種方法支援擷取指定連絡人服務的方法 (和相關資料) :ListSupportedMethodsDisplayMethod、DisplayMethodAccessDisplayFormatDisplayMethodParameters ListSupportedMethods方法會擷取支援的方法和每個方法的 GUID 識別碼計數;然後它會呼叫DisplayMethod方法。 DisplayMethod方法會呼叫IPortableDeviceServiceCapapbibility::GetMethodAttributes方法,以擷取指定方法的選項、參數等等。 在 DisplayMethod擷取方法資料之後,它會轉譯名稱 (或 GUID) 、存取限制、如果有任何) ,則會 (相關聯的格式,以及參數描述。 DisplayMethodAccessDisplayFormatDisplayMethodParameters是協助程式函式,可轉譯其各自的資料欄位。

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 方法來擷取方法的名稱。 DisplayMethod會呼叫IPortableDeviceValues::GetUnsignedIntegerValue來擷取存取 restrctions。 在此之後,它會呼叫 IPortableDeviceValues::GetGuidValue 來擷取任何相關聯的格式。 最後, DisplayMethod 會呼叫 IPortableDeviceValues::GetIPortableDeviceKeyCollectionValue 來擷取參數資料。 它會將這些方法傳回的資料傳遞至 DisplayMethodAccessDisplayFormatDisplayMethodParameters 協助程式函式,以轉譯指定方法的資訊。

下列程式碼使用 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