检索受支持的服务方法
服务方法封装每个服务定义和实现的功能。 它们特定于每种服务类型,并由唯一 GUID 表示。
例如,联系人服务定义了 一个 BeginSync 方法,应用程序调用以准备用于同步联系人对象的设备,以及用于通知设备同步已完成的 EndSync 方法。
应用程序可以使用 IPortableDeviceServiceCapabilities 接口以编程方式查询受支持的方法并访问这些方法及其属性。
不应将服务方法与 WPD 命令混淆。 WPD 命令是标准 WPD 设备驱动程序接口 (DDI) 的一部分,是 WPD 应用程序和驱动程序之间通信的机制。 命令是预定义的,按类别分组,例如WPD_CATEGORY_COMMON,并由 PROPERTYKEY 结构表示。 有关详细信息,请参阅 命令 主题。
WpdServicesApiSample 应用程序包含代码,演示如何使用下表中的接口检索给定联系人服务支持的方法。
接口 | 说明 |
---|---|
IPortableDeviceService | 用于检索 IPortableDeviceServiceCapabilities 接口以访问受支持的服务方法。 |
IPortableDeviceServiceCapabilities | 提供对受支持的方法、方法属性和方法参数的访问权限。 |
IPortableDevicePropVariantCollection | 包含受支持方法的列表。 |
IPortableDeviceValues | 包含方法的属性和给定方法的参数。 |
IPortableDeviceKeyCollection | 包含给定方法的参数。 |
当用户在命令行中选择选项“5”时,应用程序将调用 ServiceMethods.cpp 模块中找到的 ListSupportedMethods 方法。
请注意,在检索事件列表之前,示例应用程序会在连接的设备上打开联系人服务。
在 WPD 中,方法按名称、访问权限、参数和相关数据进行描述。 示例应用程序显示用户友好名称,例如“CustomMethod”或 GUID。 方法名称或 GUID 后跟访问数据 (“读/写”) 、任何关联格式的名称和参数数据。 此数据包括参数名称、用法、VARTYPE 和窗体。
ServiceMethods.cpp 模块中的五种方法支持检索给定联系人服务的方法 (和相关数据) : ListSupportedMethods、 DisplayMethod、 DisplayMethodAccess、 DisplayFormat 和 DisplayMethodParameters。 ListSupportedMethods 方法检索每个方法支持的方法和 GUID 标识符的计数;然后调用 DisplayMethod 方法。 DisplayMethod 方法调用 IPortableDeviceServiceCapapbabilities::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");
}
}
}
}
相关主题