Получение свойств для нескольких объектов
Некоторые драйверы устройств поддерживают получение свойств для нескольких объектов в одном вызове функции; это называется массовым извлечением. Существует два типа операций массового извлечения: первый тип извлекает свойства для списка объектов, а второй тип извлекает свойства для всех объектов заданного формата. В примере, описанном в этом разделе, демонстрируется прежнее.
Приложение может выполнить массовое извлечение с помощью интерфейсов, описанных в следующей таблице.
Интерфейс | Описание |
---|---|
Интерфейс 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);
}
После выполнения предыдущих шагов пример приложения инициирует асинхронное извлечение свойства. Для этого выполните указанные ниже действия.
- Вызов IPortableDevicePropertiesBulk::QueueGetValuesByObjectList, который ставит в очередь запрос на массовое получение свойств. (Обратите внимание, что хотя запрос помещается в очередь, он не запущен.)
- Вызов 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);
}
}
Связанные разделы