Mengambil Metode Layanan yang Didukung

Metode layanan merangkum fungsionalitas yang ditentukan dan diterapkan setiap layanan. Mereka khusus untuk setiap jenis layanan dan diwakili oleh GUID unik.

Misalnya, layanan Kontak mendefinisikan metode BeginSync yang dipanggil aplikasi untuk menyiapkan perangkat untuk menyinkronkan objek Kontak, dan metode EndSync untuk memberi tahu perangkat bahwa sinkronisasi telah selesai.

Aplikasi dapat secara terprogram mengkueri metode yang didukung dan mengakses metode ini dan atributnya dengan menggunakan antarmuka IPortableDeviceServiceCapabilities .

Metode layanan tidak boleh dikacaukan dengan perintah WPD. Perintah WPD adalah bagian dari Antarmuka Driver Perangkat (DDI) WPD standar, dan merupakan mekanisme untuk komunikasi antara aplikasi WPD dan driver. Perintah telah ditentukan sebelumnya, dikelompokkan menurut kategori, misalnya, WPD_CATEGORY_COMMON, dan diwakili oleh struktur PROPERTYKEY. Untuk informasi selengkapnya, lihat topik Perintah .

Aplikasi WpdServicesApiSample menyertakan kode yang menunjukkan bagaimana aplikasi dapat mengambil metode yang didukung oleh layanan Kontak tertentu dengan menggunakan antarmuka dalam tabel berikut.

Antarmuka Deskripsi
IPortableDeviceService Digunakan untuk mengambil antarmuka IPortableDeviceServiceCapabilities untuk mengakses metode layanan yang didukung.
IPortableDeviceServiceCapabilities Menyediakan akses ke metode, atribut metode, dan parameter metode yang didukung.
IPortableDevicePropVariantCollection Berisi daftar metode yang didukung.
IPortableDeviceValues Berisi atribut untuk metode dan untuk parameter metode tertentu.
IPortableDeviceKeyCollection Berisi parameter untuk metode tertentu.

 

Ketika pengguna memilih opsi "5" di baris perintah, aplikasi memanggil metode ListSupportedMethods yang ditemukan dalam modul ServiceMethods.cpp.

Perhatikan bahwa sebelum mengambil daftar peristiwa, aplikasi sampel membuka layanan Kontak pada perangkat yang terhubung.

Dalam WPD, metode dijelaskan dengan namanya, hak akses, parameter, dan data terkait. Aplikasi sampel menampilkan nama yang mudah digunakan, misalnya, "CustomMethod", atau GUID. Nama metode atau GUID diikuti oleh data akses ("Baca/Tulis"), nama format terkait, dan data parameter. Data ini mencakup nama parameter, penggunaan, VARTYPE, dan formulir.

Lima metode dalam modul ServiceMethods.cpp mendukung pengambilan metode (dan data terkait) untuk layanan Kontak yang diberikan: ListSupportedMethods, DisplayMethod, DisplayMethodAccess, DisplayFormat, dan DisplayMethodParameters. Metode ListSupportedMethods mengambil hitungan metode yang didukung dan pengidentifikasi GUID untuk masing-masing; kemudian memanggil metode DisplayMethod . Metode DisplayMethod memanggil metode IPortableDeviceServiceCapapbilities::GetMethodAttributes untuk mengambil opsi, parameter, dan sebagainya metode yang diberikan. Setelah DisplayMethod mengambil data metode, displayMethod merender nama (atau GUID), pembatasan akses, format terkait (jika ada), dan deskripsi parameter. DisplayMethodAccess, DisplayFormat, dan DisplayMethodParameters adalah fungsi pembantu yang merender bidang data masing-masing.

Metode ListSupportedMethods memanggil metode IPortableDeviceService::Capabilities untuk mengambil antarmuka IPortableDeviceServiceCapabilities . Dengan menggunakan antarmuka ini, ia mengambil metode yang didukung dengan memanggil metode IPortableDeviceServiceCapabilities::GetSupportedMethods . Metode GetSupportedMethods mengambil GUID untuk setiap metode yang didukung oleh layanan dan menyalin GUID tersebut ke dalam objek IPortableDevicePropVariantCollection .

Kode berikut menggunakan metode 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);
        }
    }    
}

Setelah metode ListSupportedMethods mengambil GUID untuk setiap peristiwa yang didukung oleh layanan tertentu, metode DisplayMethod akan memanggil metode DisplayMethod untuk mengambil atribut khusus metode. Atribut ini meliputi: nama metode yang ramah skrip, pembatasan akses yang diperlukan, format terkait, dan daftar parameter.

Metode DisplayMethod memanggil metode IPortableDeviceServiceCapabilities::GetMethodAttributes untuk mengambil kumpulan atribut untuk metode yang diberikan. Kemudian memanggil metode IPortableDeviceValues::GetStringValue untuk mengambil nama metode. DisplayMethod memanggil IPortableDeviceValues::GetUnsignedIntegerValue untuk mengambil restrction akses. Setelah ini, ia memanggil IPortableDeviceValues::GetGuidValue untuk mengambil format terkait. Dan, akhirnya, DisplayMethod memanggil IPortableDeviceValues::GetIPortableDeviceKeyCollectionValue untuk mengambil data parameter. Ini meneruskan data yang dikembalikan oleh metode ini ke fungsi pembantu DisplayMethodAccess, DisplayFormat, dan DisplayMethodParameters , yang merender informasi untuk metode yang diberikan.

Kode berikut menggunakan metode 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;

    }
}

Fungsi pembantu DisplayMethodAccess menerima nilai DWORD yang berisi opsi akses metode. Ini membandingkan nilai ini dengan WPD_COMMAND_ACCESS_READ dan WPD_COMMAND_ACCESS_READWRITE untuk menentukan hak istimewa akses metode. Dengan menggunakan hasilnya, ia merender string yang menunjukkan pembatasan akses untuk metode yang diberikan.

Kode berikut menggunakan fungsi pembantu 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;
    }
}

Fungsi pembantu DisplayMethod menerima objek IPortableDeviceServiceCapabilities dan GUID metode sebagai parameter. Menggunakan objek IPortableDeviceServiceCapabilities , ia memanggil metode IPortableDeviceServiceCapabilities::GetMethodAttributes untuk mengambil atribut metode dan merendernya di jendela konsol aplikasi.

Fungsi pembantu DisplayMethodParameters menerima objek IPortableDeviceServiceCapabilities , GUID metode, dan objek IPortableDeviceKeyCollection yang berisi parameter metode. Menggunakan objek IPortableDeviceKeyCollection , ia memanggil metode IPortableDeviceServiceCapabilities::GetMethodParameterAttributes untuk mengambil nama, penggunaan, VARTYPE, dan formulir parameter. Ini merender informasi ini di jendela konsol aplikasi.

Kode berikut menggunakan fungsi pembantu 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