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 recupera o identificador PnP para o serviço, ele pode configurar as informações do cliente e chamar IPortableDeviceService::Open.
No aplicativo de exemplo, esse método é chamado em 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. Caso contrário, ambos os ponteiros dão suporte à mesma funcionalidade.
Os aplicativos que residem em apartments de thread único devem usar CLSID_PortableDeviceServiceFTM , pois isso elimina a sobrecarga do marshaling de ponteiro de 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);
}
}
Tópicos relacionados