Apertura de un servicio

Para que la aplicación pueda realizar operaciones en un servicio, por ejemplo, enumerar contenido o recuperar descripciones de eventos o métodos admitidos, debe abrir el servicio. En la aplicación WpdServicesApiSample, esta tarea se muestra en el módulo ServiceEnumeration.cpp mediante las interfaces descritas en la tabla siguiente.

Interfaz Descripción
IPortableDeviceServiceManager Se usa para enumerar los servicios de un dispositivo.
IPortableDeviceService Se usa para abrir una conexión a un servicio de dispositivo.
IPortableDeviceValues Se usa para contener la información de cliente de la aplicación.

 

El método que abre un servicio es IPortableDeviceService::Open. Este método toma dos argumentos: un identificador Plug-and-Play (PnP) para el servicio y un objeto IPortableDeviceValues que contiene la información de cliente de la aplicación.

Para obtener un identificador PnP para un servicio determinado, la aplicación llama al método IPortableDeviceServiceManager::GetDeviceServices . Este método recupera una matriz de identificadores PnP para los servicios de un GUID de categoría de servicio (por ejemplo, Contactos de SERVICIO).

La aplicación de servicio de ejemplo recupera un identificador PnP para los servicios de contactos dentro del método EnumerateContactsServices en el módulo ServiceEnumeration.cpp. El ejemplo de código siguiente se toma de este método.

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

Después de que la aplicación recupere el identificador PnP del servicio, puede configurar la información del cliente y llamar a IPortableDeviceService::Open.

En la aplicación de ejemplo, se llama a este método en ChooseDeviceService en el módulo ServiceEnumeration.cpp.

IPortableDeviceService admite dos CLSID para CoCreateInstance. CLSID_PortableDeviceService devuelve un puntero IPortableDeviceService que no agrega el serializador de subprocesos libres; CLSID_PortableDeviceServiceFTM es un nuevo CLSID que devuelve un puntero IPortableDeviceService que agrega el serializador de subprocesos libre. Ambos punteros admiten la misma funcionalidad de lo contrario.

Las aplicaciones que residen en apartamentos de un solo subproceso deben usar CLSID_PortableDeviceServiceFTM , ya que esto elimina la sobrecarga de serialización de punteros de interfaz. CLSID_PortableDeviceService sigue siendo compatible con las aplicaciones heredadas.

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 (Interfaz)

IPortableDeviceValues (Interfaz)

IPortableDeviceServiceManager (Interfaz)

WpdServicesApiSample