Поделиться через


Получение свойств для нескольких объектов

Некоторые драйверы устройств поддерживают получение свойств для нескольких объектов в одном вызове функции; это называется массовым извлечением. Существует два типа операций массового извлечения: первый тип извлекает свойства для списка объектов, а второй тип извлекает свойства для всех объектов заданного формата. В примере, описанном в этом разделе, демонстрируется прежнее.

Приложение может выполнить массовое извлечение с помощью интерфейсов, описанных в следующей таблице.

Интерфейс Описание
Интерфейс IPortableDeviceContent Предоставляет доступ к методам, специфичным для содержимого.
Интерфейс IPortableDeviceKeyCollection Используется для идентификации свойств, которые необходимо извлечь.
интерфейс IPortableDeviceProperties Используется для определения того, поддерживает ли данный драйвер массовые операции.
Интерфейс IPortableDevicePropertiesBulk Поддерживает операцию массового извлечения.
интерфейс IPortableDevicePropVariantCollection Используется для хранения идентификаторов объектов для пакетной операции.

 

Функция ReadContentPropertiesBulk в модуле ContentProperties.cpp демонстрационного приложения демонстрирует операцию массового извлечения данных.

Первая задача, выполненная в этом примере, определяет, поддерживает ли данный драйвер массовые операции. Это достигается путем вызова QueryInterface в интерфейсе IPortableDeviceProperties и проверки наличия IPortableDevicePropertiesBulk.

HRESULT                                       hr                = S_OK;
GUID                                          guidContext       = GUID_NULL;
CGetBulkValuesCallback*                       pCallback         = NULL;
CComPtr<IPortableDeviceProperties>            pProperties;
CComPtr<IPortableDevicePropertiesBulk>        pPropertiesBulk;
CComPtr<IPortableDeviceValues>                pObjectProperties;
CComPtr<IPortableDeviceContent>               pContent;
CComPtr<IPortableDeviceKeyCollection>         pPropertiesToRead;
CComPtr<IPortableDevicePropVariantCollection> pObjectIDs;


if (SUCCEEDED(hr))
{
    hr = pDevice->Content(&pContent);
    if (FAILED(hr))
    {
        printf("! Failed to get IPortableDeviceContent from IPortableDevice, hr = 0x%lx\n",hr);
    }
}



if (SUCCEEDED(hr))
{
    hr = pContent->Properties(&pProperties);
    if (FAILED(hr))
    {
        printf("! Failed to get IPortableDeviceProperties from IPortableDevice, hr = 0x%lx\n",hr);
    }
}



if (SUCCEEDED(hr))
{
    hr = pProperties->QueryInterface(IID_PPV_ARGS(&pPropertiesBulk));
    if (FAILED(hr))
    {
        printf("This driver does not support BULK property operations.\n");
    }
}

Если драйвер поддерживает массовые операции, необходимо создать экземпляр интерфейса IPortableDeviceKeyCollectionи указать ключи, соответствующие свойствам, которые будут получены приложением. Для описания этого процесса см. в разделе "Получение свойств для одного объекта".

После указания соответствующих ключей пример приложения создает экземпляр интерфейса IPortableDevicePropertiesBulkCallback. Приложение будет использовать методы в этом интерфейсе для отслеживания хода выполнения асинхронной операции массового извлечения.

if (SUCCEEDED(hr))
{
    pCallback = new CGetBulkValuesCallback();
    if (pCallback == NULL)
    {
        hr = E_OUTOFMEMORY;
        printf("! Failed to allocate CGetBulkValuesCallback, hr = 0x%lx\n", hr);
    }
}

Следующая функция, вызываемая примером приложения, является вспомогательной функцией CreateIPortableDevicePropVariantCollectionWithAllObjectIDs. Эта функция создает список всех доступных идентификаторов объектов для примеров. (Реальное приложение ограничивает список идентификаторов определенным набором объектов. Например, приложение может создать список идентификаторов для всех объектов в текущем представлении папок.)

Как отмечалось выше, вспомогательные функции рекурсивно перечисляют все объекты на определенном устройстве. Он возвращает этот список в интерфейсе IPortableDevicePropVariantCollection, который содержит идентификатор для каждого найденного объекта. В модуле ContentEnumeration.cpp определена вспомогательная функция.

// 7) Call our helper function CreateIPortableDevicePropVariantCollectionWithAllObjectIDs
// to enumerate and create an IPortableDevicePropVariantCollection with the object
// identifiers needed to perform the bulk operation on.
if (SUCCEEDED(hr))
{
    hr = CreateIPortableDevicePropVariantCollectionWithAllObjectIDs(pDevice,
                                                                    pContent,
                                                                    &pObjectIDs);
}

После выполнения предыдущих шагов пример приложения инициирует асинхронное извлечение свойства. Для этого выполните указанные ниже действия.

  1. Вызов IPortableDevicePropertiesBulk::QueueGetValuesByObjectList, который ставит в очередь запрос на массовое получение свойств. (Обратите внимание, что хотя запрос помещается в очередь, он не запущен.)
  2. Вызов IPortableDevicePropertiesBulk::Start для запуска очередного запроса.

Эти шаги показаны в следующем фрагменте кода из примера приложения.

   if (SUCCEEDED(hr))
   {
       hr = pPropertiesBulk->QueueGetValuesByObjectList(pObjectIDs,
                                                        pPropertiesToRead,
                                                        pCallback,
                                                        &guidContext);


       if(SUCCEEDED(hr))
       {
           // Cleanup any previously created global event handles.
           if (g_hBulkPropertyOperationEvent != NULL)
           {
               CloseHandle(g_hBulkPropertyOperationEvent);
               g_hBulkPropertyOperationEvent = NULL;
           }

           // In order to create a simpler to follow example we create and wait infinitly
           // for the bulk property operation to complete and ignore any errors.
           // Production code should be written in a more robust manner.
           // Create the global event handle to wait on for the bulk operation
           // to complete.
           g_hBulkPropertyOperationEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
           if (g_hBulkPropertyOperationEvent != NULL)
           {
               // Call Start() to actually being the Asynchronous bulk operation.
               hr = pPropertiesBulk->Start(guidContext);
               if(FAILED(hr))
               {
                   printf("! Failed to start property operation, hr = 0x%lx\n", hr);
               }
           }
           else
           {
               printf("! Failed to create the global event handle to wait on for the bulk operation. Aborting operation.\n");
           }
       }
       else
       {
           printf("! QueueGetValuesByObjectList Failed, hr = 0x%lx\n", hr);
       }
   }

интерфейс IPortableDevice

интерфейс IPortableDeviceContent

интерфейс IPortableDeviceKeyCollection

Интерфейс IPortableDeviceProperties

Интерфейс IPortableDevicePropertiesBulk

интерфейс IPortableDevicePropVariantCollection

Руководство по программированию