擷取多個物件的屬性
某些設備磁碟機支援在單一函式呼叫中擷取多個物件的屬性;這稱為大量擷取。 大量擷取作業有兩種類型:第一種類型會擷取物件清單的屬性,而第二種類型會擷取指定格式之所有物件的屬性。 本節所述的範例示範前者。
您的應用程式可以使用下表所述的介面來執行大量擷取。
介面 | 描述 |
---|---|
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 協助程式函式。 此函式會針對範例用途,建立所有可用物件識別碼的清單。 (真實世界應用程式會將識別碼清單限制為一組特定的物件。例如,應用程式可能會為目前位於指定資料夾檢視中的所有物件建立識別碼清單。)
如上所述,協助程式函式會以遞迴方式列舉指定裝置上的所有物件。 它會在 IPortableDevicePropVariantCollection 介面 中傳回此清單,其中包含其找到之每個物件的識別碼。 Helper 函式定義于 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);
}
}
相關主題