Получение поддерживаемых методов службы
Методы службы инкапсулируют функциональные возможности, которые каждая служба определяет и реализует. Они относятся к каждому типу службы и представлены уникальным идентификатором GUID.
Например, служба "Контакты" определяет метод BeginSync , вызываемый приложениями для подготовки устройства к синхронизации объектов Contact, и метод EndSync для уведомления устройства о завершении синхронизации.
Приложения могут программно запрашивать поддерживаемые методы и получать доступ к этим методам и их атрибутам с помощью интерфейса IPortableDeviceServiceCapabilities .
Методы службы не следует путать с командами WPD. Команды WPD являются частью стандартного интерфейса драйвера устройства WPD (DDI) и являются механизмом взаимодействия между приложением WPD и драйвером. Команды являются предопределенными, сгруппированы по категориям, например WPD_CATEGORY_COMMON, и представлены структурой PROPERTYKEY. Дополнительные сведения см. в разделе Команды .
Приложение WpdServicesApiSample содержит код, демонстрирующий, как приложение может получить методы, поддерживаемые данной службой контактов, с помощью интерфейсов, приведенных в следующей таблице.
Интерфейс | Описание |
---|---|
IPortableDeviceService | Используется для получения интерфейса IPortableDeviceServiceCapabilities для доступа к поддерживаемым методам службы. |
IPortableDeviceServiceCapabilities | Предоставляет доступ к поддерживаемым методам, атрибутам метода и параметрам метода. |
IPortableDevicePropVariantCollection | Содержит список поддерживаемых методов. |
IPortableDeviceValues | Содержит атрибуты для метода и параметров данного метода. |
IPortableDeviceKeyCollection | Содержит параметры для заданного метода. |
Когда пользователь выбирает параметр "5" в командной строке, приложение вызывает метод ListSupportedMethods , который находится в модуле ServiceMethods.cpp.
Обратите внимание, что перед получением списка событий пример приложения открывает службу контактов на подключенном устройстве.
В WPD метод описывается его именем, правами доступа, параметрами и связанными данными. В примере приложения отображается понятное имя, например CustomMethod или GUID. За именем метода или GUID следуют данные доступа ("Чтение и запись"), имя любого связанного формата и данные параметров. Эти данные включают имя параметра, использование, VARTYPE и форму.
Пять методов в модуле ServiceMethods.cpp поддерживают получение методов (и связанных данных) для данной службы контактов: ListSupportedMethods, DisplayMethod, DisplayMethodAccess, DisplayFormat и DisplayMethodParameters. Метод ListSupportedMethods получает количество поддерживаемых методов и идентификатор GUID для каждого из них; Затем он вызывает метод DisplayMethod . Метод DisplayMethod вызывает метод IPortableDeviceServiceCapapbilities::GetMethodAttributes для получения параметров, параметров и т. д. После того как DisplayMethod извлекает данные метода, он отображает имя (или GUID), ограничения доступа, связанный формат (если таковой есть) и описания параметров. DisplayMethodAccess, DisplayFormat и DisplayMethodParameters — это вспомогательные функции, которые отрисовывают соответствующие поля данных.
Метод ListSupportedMethods вызывает метод IPortableDeviceService::Capabilities для получения интерфейса IPortableDeviceServiceCapabilities . С помощью этого интерфейса он получает поддерживаемые методы, вызывая метод IPortableDeviceServiceCapabilities::GetSupportedMethods . Метод GetSupportedMethods извлекает идентификаторы GUID для каждого метода, поддерживаемого службой, и копирует этот GUID в объект IPortableDevicePropVariantCollection .
В следующем коде используется метод ListSupportedMethods .
// List all supported methods on the service
void ListSupportedMethods(IPortableDeviceService* pService)
{
HRESULT hr = S_OK;
DWORD dwNumMethods = 0;
CComPtr<IPortableDeviceServiceCapabilities> pCapabilities;
CComPtr<IPortableDevicePropVariantCollection> pMethods;
if (pService == NULL)
{
printf("! A NULL IPortableDeviceService interface pointer was received\n");
return;
}
// Get an IPortableDeviceServiceCapabilities interface from the IPortableDeviceService interface to
// access the service capabilities-specific methods.
hr = pService->Capabilities(&pCapabilities);
if (FAILED(hr))
{
printf("! Failed to get IPortableDeviceServiceCapabilities from IPortableDeviceService, hr = 0x%lx\n",hr);
}
// Get all methods supported by the service.
if (SUCCEEDED(hr))
{
hr = pCapabilities->GetSupportedMethods(&pMethods);
if (FAILED(hr))
{
printf("! Failed to get supported methods from the service, hr = 0x%lx\n",hr);
}
}
// Get the number of supported methods found on the service.
if (SUCCEEDED(hr))
{
hr = pMethods->GetCount(&dwNumMethods);
if (FAILED(hr))
{
printf("! Failed to get number of supported methods, hr = 0x%lx\n",hr);
}
}
printf("\n%d Supported Methods Found on the service\n\n", dwNumMethods);
// Loop through each method and display it
if (SUCCEEDED(hr))
{
for (DWORD dwIndex = 0; dwIndex < dwNumMethods; dwIndex++)
{
PROPVARIANT pv = {0};
PropVariantInit(&pv);
hr = pMethods->GetAt(dwIndex, &pv);
if (SUCCEEDED(hr))
{
// We have a method. It is assumed that
// methods are returned as VT_CLSID VarTypes.
if (pv.puuid != NULL)
{
DisplayMethod(pCapabilities, *pv.puuid);
printf("\n");
}
}
PropVariantClear(&pv);
}
}
}
После того как метод ListSupportedMethods получает GUID для каждого события, поддерживаемого данной службой, он вызывает метод DisplayMethod для получения атрибутов, относящихся к методу. К этим атрибутам относятся: понятное для скрипта имя метода, обязательные ограничения доступа, любой связанный формат и список параметров.
Метод DisplayMethod вызывает метод IPortableDeviceServiceCapabilities::GetMethodAttributes для получения коллекции атрибутов для данного метода. Затем он вызывает метод IPortableDeviceValues::GetStringValue для получения имени метода. DisplayMethod вызывает IPortableDeviceValues::GetUnsignedIntegerValue для получения restrctions доступа. После этого он вызывает IPortableDeviceValues::GetGuidValue для получения любого связанного формата. И, наконец, DisplayMethod вызывает IPortableDeviceValues::GetIPortableDeviceKeyCollectionValue для получения данных параметра. Он передает данные, возвращаемые этими методами, во вспомогательные функции DisplayMethodAccess, DisplayFormat и DisplayMethodParameters , которые отображают сведения для данного метода.
В следующем коде используется метод DisplayMethod .
// Display basic information about a method
void DisplayMethod(
IPortableDeviceServiceCapabilities* pCapabilities,
REFGUID Method)
{
CComPtr<IPortableDeviceValues> pAttributes;
// Get the method attributes which describe the method
HRESULT hr = pCapabilities->GetMethodAttributes(Method, &pAttributes);
if (FAILED(hr))
{
printf("! Failed to get the method attributes, hr = 0x%lx\n",hr);
}
if (SUCCEEDED(hr))
{
PWSTR pszMethodName = NULL;
DWORD dwMethodAccess = WPD_COMMAND_ACCESS_READ;
GUID guidFormat = GUID_NULL;
CComPtr<IPortableDeviceValues> pOptions;
CComPtr<IPortableDeviceKeyCollection> pParameters;
// Display the name of the method if available. Otherwise, fall back to displaying the GUID.
hr = pAttributes->GetStringValue(WPD_METHOD_ATTRIBUTE_NAME, &pszMethodName);
if (SUCCEEDED(hr))
{
printf("%ws", pszMethodName);
}
else
{
printf("%ws", (PWSTR)CGuidToString(Method));
}
// Display the method access if available, otherwise default to WPD_COMMAND_ACCESS_READ access
hr = pAttributes->GetUnsignedIntegerValue(WPD_METHOD_ATTRIBUTE_ACCESS, &dwMethodAccess);
if (FAILED(hr))
{
dwMethodAccess = WPD_COMMAND_ACCESS_READ;
hr = S_OK;
}
printf("\n\tAccess: ");
DisplayMethodAccess(dwMethodAccess);
// Display the associated format if specified.
// Methods that have an associated format may only be supported for that format.
// Methods that don't have associated formats generally apply to the entire service.
hr = pAttributes->GetGuidValue(WPD_METHOD_ATTRIBUTE_ASSOCIATED_FORMAT, &guidFormat);
if (SUCCEEDED(hr))
{
printf("\n\tAssociated Format: ");
DisplayFormat(pCapabilities, guidFormat);
}
// Display the method parameters, if available
hr = pAttributes->GetIPortableDeviceKeyCollectionValue(WPD_METHOD_ATTRIBUTE_PARAMETERS, &pParameters);
if (SUCCEEDED(hr))
{
DisplayMethodParameters(pCapabilities, Method, pParameters);
}
CoTaskMemFree(pszMethodName);
pszMethodName = NULL;
}
}
Вспомогающая функция DisplayMethodAccess получает значение DWORD, содержащее параметры доступа метода. Он сравнивает это значение с WPD_COMMAND_ACCESS_READ и WPD_COMMAND_ACCESS_READWRITE для определения привилегии доступа метода. Используя результат, он отображает строку, указывающую ограничение доступа для данного метода.
В следующем коде используется вспомогащая функция DisplayMethodAccess .
void DisplayMethodAccess(
DWORD dwAccess)
{
switch(static_cast<WPD_COMMAND_ACCESS_TYPES>(dwAccess))
{
case WPD_COMMAND_ACCESS_READ:
printf("Read");
break;
case WPD_COMMAND_ACCESS_READWRITE:
printf("Read/Write");
break;
default:
printf("Unknown Access");
break;
}
}
Вспомогательская функция DisplayMethod получает объект IPortableDeviceServiceCapabilities и GUID метода в качестве параметров. Используя объект IPortableDeviceServiceCapabilities , он вызывает метод IPortableDeviceServiceCapabilities::GetMethodAttributes для получения атрибутов метода и их отображения в окне консоли приложения.
Вспомогающая функция DisplayMethodParameters получает объект IPortableDeviceServiceCapabilities , GUID метода и объект IPortableDeviceKeyCollection, содержащий параметры метода. Используя объект IPortableDeviceKeyCollection , он вызывает метод IPortableDeviceServiceCapabilities::GetMethodParameterAttributes для получения имени, использования, VARTYPE и формы параметра. Эти сведения отображаются в окне консоли приложения.
В следующем коде используется вспомогащая функция DisplayMethodParameters .
// Display the method parameters.
void DisplayMethodParameters(
IPortableDeviceServiceCapabilities* pCapabilities,
REFGUID Method,
IPortableDeviceKeyCollection* pParameters)
{
DWORD dwNumParameters = 0;
// Get the number of parameters for this event.
HRESULT hr = pParameters->GetCount(&dwNumParameters);
if (FAILED(hr))
{
printf("! Failed to get number of parameters, hr = 0x%lx\n",hr);
}
printf("\n\t%d Method Parameters:\n", dwNumParameters);
// Loop through each parameter and display it
if (SUCCEEDED(hr))
{
for (DWORD dwIndex = 0; dwIndex < dwNumParameters; dwIndex++)
{
PROPERTYKEY parameter;
hr = pParameters->GetAt(dwIndex, ¶meter);
if (SUCCEEDED(hr))
{
CComPtr<IPortableDeviceValues> pAttributes;
// Display the parameter's Name, Usage, Vartype, and Form
hr = pCapabilities->GetMethodParameterAttributes(Method, parameter, &pAttributes);
if (FAILED(hr))
{
printf("! Failed to get the method parameter attributes, hr = 0x%lx\n",hr);
}
if (SUCCEEDED(hr))
{
PWSTR pszParameterName = NULL;
DWORD dwAttributeVarType = 0;
DWORD dwAttributeForm = WPD_PARAMETER_ATTRIBUTE_FORM_UNSPECIFIED;
DWORD dwAttributeUsage = (DWORD)-1;
hr = pAttributes->GetStringValue(WPD_PARAMETER_ATTRIBUTE_NAME, &pszParameterName);
if (SUCCEEDED(hr))
{
printf("\t\tName: %ws\n", pszParameterName);
}
else
{
printf("! Failed to get the method parameter name, hr = 0x%lx\n",hr);
}
// Read the WPD_PARAMETER_ATTRIBUTE_USAGE value, if specified.
hr = pAttributes->GetUnsignedIntegerValue(WPD_PARAMETER_ATTRIBUTE_USAGE, &dwAttributeUsage);
if (SUCCEEDED(hr))
{
printf("\t\tUsage: ");
DisplayParameterUsage(dwAttributeUsage);
printf("\n");
}
else
{
printf("! Failed to get the method parameter usage, hr = 0x%lx\n",hr);
}
hr = pAttributes->GetUnsignedIntegerValue(WPD_PARAMETER_ATTRIBUTE_VARTYPE, &dwAttributeVarType);
if (SUCCEEDED(hr))
{
printf("\t\tVARTYPE: ");
DisplayVarType(static_cast<VARTYPE>(dwAttributeVarType));
printf("\n");
}
else
{
printf("! Failed to get the method parameter VARTYPE, hr = 0x%lx\n",hr);
}
// Read the WPD_PARAMETER_ATTRIBUTE_FORM value.
hr = pAttributes->GetUnsignedIntegerValue(WPD_PARAMETER_ATTRIBUTE_FORM, &dwAttributeForm);
if (FAILED(hr))
{
// If the read fails, assume WPD_PARAMETER_ATTRIBUTE_FORM_UNSPECIFIED
dwAttributeForm = WPD_PARAMETER_ATTRIBUTE_FORM_UNSPECIFIED;
hr = S_OK;
}
printf("\t\tForm: ");
DisplayParameterForm(dwAttributeForm);
printf("\n");
CoTaskMemFree(pszParameterName);
pszParameterName = NULL;
}
printf("\n");
}
}
}
}
Связанные темы