Recuperando métodos de serviço com suporte
Os métodos de serviço encapsulam a funcionalidade que cada serviço define e implementa. Eles são específicos para cada tipo de serviço e são representados por um GUID exclusivo.
Por exemplo, o serviço Contatos define um método BeginSync que os aplicativos chamam para preparar o dispositivo para sincronizar objetos contact e um método EndSync para notificar o dispositivo que a sincronização foi concluída.
Os aplicativos podem consultar programaticamente os métodos com suporte e acessar esses métodos e seus atributos usando a interface IPortableDeviceServiceCapabilities .
Os métodos de serviço não devem ser confundidos com comandos WPD. Os comandos WPD fazem parte da DDI (Interface de Driver de Dispositivo) do WPD padrão e são o mecanismo de comunicação entre um aplicativo WPD e o driver. Os comandos são predefinidos, agrupados por categorias, por exemplo, WPD_CATEGORY_COMMON e são representados por uma estrutura PROPERTYKEY. Para obter mais informações, consulte o tópico Comandos .
O aplicativo WpdServicesApiSample inclui código que demonstra como um aplicativo pode recuperar os métodos compatíveis com determinado serviço Contatos usando as interfaces na tabela a seguir.
Interface | Descrição |
---|---|
IPortableDeviceService | Usado para recuperar a interface IPortableDeviceServiceCapabilities para acessar os métodos de serviço com suporte. |
IPortableDeviceServiceCapabilities | Fornece acesso aos métodos com suporte, atributos de método e parâmetros de método. |
IPortableDevicePropVariantCollection | Contém a lista de métodos com suporte. |
IPortableDeviceValues | Contém os atributos de um método e para os parâmetros de um determinado método. |
IPortableDeviceKeyCollection | Contém os parâmetros de um determinado método. |
Quando o usuário escolhe a opção "5" na linha de comando, o aplicativo invoca o método ListSupportedMethods encontrado no módulo ServiceMethods.cpp.
Observe que, antes de recuperar a lista de eventos, o aplicativo de exemplo abre um serviço Contatos em um dispositivo conectado.
No WPD, um método é descrito por seu nome, direitos de acesso, parâmetros e dados relacionados. O aplicativo de exemplo exibe um nome amigável, por exemplo, "CustomMethod" ou guid. O nome do método ou GUID é seguido por dados de acesso ("Leitura/Gravação"), o nome de qualquer formato associado e os dados do parâmetro. Esses dados incluem o nome do parâmetro, o uso, o VARTYPE e o formulário.
Cinco métodos no módulo ServiceMethods.cpp dão suporte à recuperação de métodos (e dados relacionados) para o serviço contatos especificado: ListSupportedMethods, DisplayMethod, DisplayMethodAccess, DisplayFormat e DisplayMethodParameters. O método ListSupportedMethods recupera uma contagem de métodos com suporte e o identificador GUID para cada um; em seguida, chama o método DisplayMethod . O método DisplayMethod chama o método IPortableDeviceServiceCapapbilities::GetMethodAttributes para recuperar as opções, os parâmetros e assim por diante do método especificado. Depois que o DisplayMethod recupera os dados do método, ele renderiza o nome (ou GUID), as restrições de acesso, o formato associado (se houver) e as descrições do parâmetro. DisplayMethodAccess, DisplayFormat e DisplayMethodParameters são funções auxiliares que renderizam seus respectivos campos de dados.
O método ListSupportedMethods invoca o método IPortableDeviceService::Capabilities para recuperar uma interface IPortableDeviceServiceCapabilities . Usando essa interface, ela recupera os métodos compatíveis chamando o método IPortableDeviceServiceCapabilities::GetSupportedMethods . O método GetSupportedMethods recupera os GUIDs para cada método com suporte do serviço e copia esse GUID em um objeto IPortableDevicePropVariantCollection .
O código a seguir usa o método 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);
}
}
}
Depois que o método ListSupportedMethods recupera o GUID para cada evento com suporte do serviço fornecido, ele invoca o método DisplayMethod para recuperar os atributos específicos do método. Esses atributos incluem: o nome amigável ao script do método, restrições de acesso necessárias, qualquer formato associado e lista de parâmetros.
O método DisplayMethod invoca o método IPortableDeviceServiceCapabilities::GetMethodAttributes para recuperar uma coleção de atributos para o método especificado. Em seguida, ele chama o método IPortableDeviceValues::GetStringValue para recuperar o nome do método. O DisplayMethod chama iPortableDeviceValues::GetUnsignedIntegerValue para recuperar as restrções de acesso. Depois disso, ele chama IPortableDeviceValues::GetGuidValue para recuperar qualquer formato associado. E, por fim, o DisplayMethod chama iPortableDeviceValues::GetIPortableDeviceKeyCollectionValue para recuperar os dados do parâmetro. Ele passa os dados retornados por esses métodos para as funções auxiliares DisplayMethodAccess, DisplayFormat e DisplayMethodParameters , que renderizam as informações para o método especificado.
O código a seguir usa o método 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;
}
}
A função auxiliar DisplayMethodAccess recebe um valor DWORD que contém as opções de acesso do método. Ele compara esse valor com WPD_COMMAND_ACCESS_READ e WPD_COMMAND_ACCESS_READWRITE para determinar o privilégio de acesso do método. Usando o resultado, ele renderiza uma cadeia de caracteres que indica a restrição de acesso para o método especificado.
O código a seguir usa a função auxiliar 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;
}
}
A função auxiliar DisplayMethod recebe um objeto IPortableDeviceServiceCapabilities e o GUID do método como parâmetros. Usando o objeto IPortableDeviceServiceCapabilities , ele invoca o método IPortableDeviceServiceCapabilities::GetMethodAttributes para recuperar os atributos do método e renderizá-los na janela do console do aplicativo.
A função auxiliar DisplayMethodParameters recebe um objeto IPortableDeviceServiceCapabilities , o GUID do método e um objeto IPortableDeviceKeyCollection que contém os parâmetros do método. Usando o objeto IPortableDeviceKeyCollection , ele invoca o método IPortableDeviceServiceCapabilities::GetMethodParameterAttributes para recuperar o nome, o uso, o VARTYPE e o formulário do parâmetro. Ele renderiza essas informações na janela do console do aplicativo.
O código a seguir usa a função auxiliar 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");
}
}
}
}
Tópicos relacionados