Abrindo um serviço

Antes que seu aplicativo possa executar operações em um serviço, por exemplo, enumerando conteúdo ou recuperando descrições de eventos ou métodos com suporte, ele deve abrir o serviço. No aplicativo WpdServicesApiSample, essa tarefa é demonstrada no módulo ServiceEnumeration.cpp usando as interfaces descritas na tabela a seguir.

Interface Descrição
IPortableDeviceServiceManager Usado para enumerar os serviços em um dispositivo.
IPortableDeviceService Usado para abrir uma conexão com um serviço de dispositivo.
IPortableDeviceValues Usado para armazenar as informações do cliente do aplicativo.

 

O método que abre um serviço é IPortableDeviceService::Open. Esse método usa dois argumentos: um identificador PnP (Plug-and-Play) para o serviço e um objeto IPortableDeviceValues que contém as informações do cliente do aplicativo.

Para obter um identificador PnP para um determinado serviço, seu aplicativo chama o método IPortableDeviceServiceManager::GetDeviceServices . Esse método recupera uma matriz de identificadores PnP para serviços de um GUID de categoria de serviço (por exemplo, Contatos DE SERVIÇO).

O aplicativo de serviço de exemplo recupera um identificador PnP para serviços de Contatos dentro do método EnumerateContactsServices no módulo ServiceEnumeration.cpp. O exemplo de código a seguir é obtido desse 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);
        }
    }
}

Depois que o aplicativo recuperar o identificador PnP para o serviço, ele poderá configurar as informações do cliente e chamar IPortableDeviceService::Open.

No aplicativo de exemplo, esse método é chamado no ChooseDeviceService no módulo ServiceEnumeration.cpp.

IPortableDeviceService dá suporte a dois CLSIDs para CoCreateInstance. CLSID_PortableDeviceService retorna um ponteiro IPortableDeviceService que não agrega o marshaler de thread livre; CLSID_PortableDeviceServiceFTM é um novo CLSID que retorna um ponteiro IPortableDeviceService que agrega o marshaler de thread livre. Ambos os ponteiros dão suporte à mesma funcionalidade caso contrário.

Os aplicativos que residem em Apartamentos Threaded Únicos devem usar CLSID_PortableDeviceServiceFTM , pois isso elimina a sobrecarga do marshaling do ponteiro da interface. CLSID_PortableDeviceService ainda tem suporte para aplicativos herdados.

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