Ouverture d’un service

Avant que votre application puisse effectuer des opérations sur un service, par exemple en énumérant du contenu ou en récupérant des descriptions d’événements ou de méthodes pris en charge, elle doit ouvrir le service. Dans l’application WpdServicesApiSample, cette tâche est illustrée dans le module ServiceEnumeration.cpp à l’aide des interfaces décrites dans le tableau suivant.

Interface Description
IPortableDeviceServiceManager Permet d’énumérer les services sur un appareil.
IPortableDeviceService Permet d’ouvrir une connexion à un service d’appareil.
IPortableDeviceValues Utilisé pour contenir les informations client de l’application.

 

La méthode qui ouvre un service est IPortableDeviceService::Open. Cette méthode prend deux arguments : un identificateur Plug-and-Play (PnP) pour le service et un objet IPortableDeviceValues qui contient les informations client de l’application.

Pour obtenir un identificateur PnP pour un service donné, votre application appelle la méthode IPortableDeviceServiceManager::GetDeviceServices . Cette méthode récupère un tableau d’identificateurs PnP pour les services d’un GUID de catégorie de service (par exemple, CONTACTS SERVICE).

L’exemple d’application service récupère un identificateur PnP pour les services de contacts au sein de la méthode EnumerateContactsServices dans le module ServiceEnumeration.cpp. L’exemple de code suivant est extrait de cette méthode.

// For each device found, find the contacts service
for (dwIndex = 0; dwIndex < cPnpDeviceIDs; dwIndex++)
{
    DWORD   cPnpServiceIDs = 0;
    PWSTR   pPnpServiceID  = NULL;

    // First, pass NULL as the PWSTR array pointer to get the total number
    // of contacts services (SERVICE_Contacts) found on the device.
    // To find the total number of all services on the device, use GUID_DEVINTERFACE_WPD_SERVICE.
    hr = pServiceManager->GetDeviceServices(pPnpDeviceIDs[dwIndex], SERVICE_Contacts, NULL, &cPnpServiceIDs);
    
    if (SUCCEEDED(hr) && (cPnpServiceIDs > 0))
    {                               
        // For simplicity, we are only using the first contacts service on each device
        cPnpServiceIDs = 1;
        hr = pServiceManager->GetDeviceServices(pPnpDeviceIDs[dwIndex], SERVICE_Contacts, &pPnpServiceID, &cPnpServiceIDs);

        if (SUCCEEDED(hr))
        {
            // We've found the service, display it and save its PnP Identifier
            ContactsServicePnpIDs.Add(pPnpServiceID);

            printf("[%d] ", static_cast<DWORD>(ContactsServicePnpIDs.GetCount()-1));

            // Display information about the device that contains this service.
            DisplayDeviceInformation(pServiceManager, pPnpServiceID);

            // ContactsServicePnpIDs now owns the memory for this string
            pPnpServiceID = NULL;
        }
        else
        {
            printf("! Failed to get the first contacts service from '%ws, hr = 0x%lx\n",pPnpDeviceIDs[dwIndex],hr);
        }
    }
}

Une fois que votre application a récupéré l’identificateur PnP pour le service, elle peut configurer les informations client et appeler IPortableDeviceService::Open.

Dans l’exemple d’application, cette méthode est appelée dans ChooseDeviceService dans le module ServiceEnumeration.cpp.

IPortableDeviceService prend en charge deux CLSID pour CoCreateInstance. CLSID_PortableDeviceService retourne un pointeur IPortableDeviceService qui n’agrège pas le marshaler à thread libre ; CLSID_PortableDeviceServiceFTM est un nouveau CLSID qui retourne un pointeur IPortableDeviceService qui agrège le marshaler à thread libre. Sinon, les deux pointeurs prennent en charge les mêmes fonctionnalités.

Les applications qui vivent dans les appartements à thread unique doivent utiliser CLSID_PortableDeviceServiceFTM car cela élimine la surcharge du marshaling des pointeurs d’interface. CLSID_PortableDeviceService est toujours pris en charge pour les applications héritées.

hr = CoCreateInstance(CLSID_PortableDeviceServiceFTM,
                      NULL,
                      CLSCTX_INPROC_SERVER,
                      IID_PPV_ARGS(&pService));
if (SUCCEEDED(hr))
{
    hr = pService->Open(ContactsServicesArray[uiCurrentService], pClientInformation);
    if (FAILED(hr))
    {
        if (hr == E_ACCESSDENIED)
        {
            printf("Failed to Open the service for Read Write access, will open it for Read-only access instead\n");

            pClientInformation->SetUnsignedIntegerValue(WPD_CLIENT_DESIRED_ACCESS, GENERIC_READ);

            hr = pService->Open(ContactsServicesArray[uiCurrentService], pClientInformation);

            if (FAILED(hr))
            {
                printf("! Failed to Open the service for Read access, hr = 0x%lx\n",hr);
            }
        }
        else
        {
            printf("! Failed to Open the service, hr = 0x%lx\n",hr);
        }
    }

IPortableDeviceService, interface

IPortableDeviceValues, interface

IPortableDeviceServiceManager, interface

WpdServicesApiSample