Открытие службы
Прежде чем приложение сможет выполнять операции со службой, например перечисление содержимого или получение описания поддерживаемых событий или методов, оно должно открыть службу. В приложении WpdServicesApiSample эта задача демонстрируется в модуле ServiceEnumeration.cpp с помощью интерфейсов, описанных в следующей таблице.
Интерфейс | Описание |
---|---|
IPortableDeviceServiceManager | Используется для перечисления служб на устройстве. |
IPortableDeviceService | Используется для открытия подключения к службе устройств. |
IPortableDeviceValues | Используется для хранения сведений о клиенте приложения. |
Метод, открывающий службу, — IPortableDeviceService::Open. Этот метод принимает два аргумента: идентификатор Plug-and-Play (PnP) для службы и объект IPortableDeviceValues , содержащий сведения о клиенте приложения.
Чтобы получить идентификатор PnP для данной службы, приложение вызывает метод IPortableDeviceServiceManager::GetDeviceServices . Этот метод извлекает массив идентификаторов PnP для служб GUID категории службы (например, контакты СЛУЖБЫ).
Пример приложения службы извлекает идентификатор PnP для служб Contacts в методе EnumerateContactsServices в модуле ServiceEnumeration.cpp. Следующий пример кода взят из этого метода.
// 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);
}
}
}
После получения идентификатора PnP для службы приложение может настроить сведения о клиенте и вызвать IPortableDeviceService::Open.
В примере приложения этот метод вызывается в файле ChooseDeviceService в модуле ServiceEnumeration.cpp.
IPortableDeviceService поддерживает два CLSID для CoCreateInstance. CLSID_PortableDeviceService возвращает указатель IPortableDeviceService , который не агрегирует маршалер без потоков; CLSID_PortableDeviceServiceFTM — это новый CLSID, который возвращает указатель IPortableDeviceService , который объединяет маршалер с свободным потоком. Оба указателя поддерживают одну и ту же функциональность в противном случае.
Приложения, которые живут в однопоточных квартирах, должны использовать CLSID_PortableDeviceServiceFTM , так как это устраняет затраты на маршалинг указателя интерфейса. CLSID_PortableDeviceService по-прежнему поддерживается для устаревших приложений.
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);
}
}
Связанные темы