检索多个对象的属性
某些设备驱动程序支持在单个函数调用中检索多个对象的属性;这称为批量检索。 有两种类型的批量检索操作:第一种类型检索对象列表的属性,第二种类型检索给定格式的所有对象的属性。 本节中所述的示例演示了前者。
应用程序可以使用下表中所述的接口执行批量检索。
接口 | 说明 |
---|---|
IPortableDeviceContent 接口 | 提供对特定于内容的方法的访问。 |
IPortableDeviceKeyCollection 接口 | 用于标识要检索的属性。 |
IPortableDeviceProperties 接口 | 用于确定给定驱动程序是否支持批量操作。 |
IPortableDevicePropertiesBulk 接口 | 支持批量检索操作。 |
IPortableDevicePropVariantCollection 接口 | 用于存储批量操作的对象标识符。 |
示例应用程序的 ContentProperties.cpp 模块中的 ReadContentPropertiesBulk 函数演示了批量检索操作。
此示例中完成的第一个任务是确定给定的驱动程序是否支持批量操作。 这是通过在 IPortableDeviceProperties 接口上调用 QueryInterface 并检查是否存在 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 帮助程序函数。 此函数创建所有可用对象标识符的列表,例如。 (实际应用程序会将标识符列表限制为一组特定的对象。例如,应用程序可能会为当前位于给定文件夹 view 中的所有对象创建标识符列表。)
如上所述,帮助程序函数以递归方式枚举给定设备上的所有对象。 它在 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);
}
}
相关主题