Recupero di proprietà per più oggetti
Alcuni driver di dispositivo supportano il recupero di proprietà per più oggetti in una singola chiamata di funzione; si tratta di un recupero bulk. Esistono due tipi di operazioni di recupero bulk: il primo tipo recupera le proprietà per un elenco di oggetti e il secondo tipo recupera le proprietà per tutti gli oggetti di un determinato formato. Nell'esempio descritto in questa sezione viene illustrato il precedente.
L'applicazione può eseguire un recupero bulk usando le interfacce descritte nella tabella seguente.
Interfaccia | Descrizione |
---|---|
Interfaccia IPortableDeviceContent | Fornisce l'accesso ai metodi specifici del contenuto. |
Interfaccia IPortableDeviceKeyCollection | Consente di identificare le proprietà da recuperare. |
Interfaccia IPortableDeviceProperties | Usato per determinare se un determinato driver supporta le operazioni bulk. |
Interfaccia IPortableDevicePropertiesBulk | Supporta l'operazione di recupero bulk. |
Interfaccia IPortableDevicePropVariantCollection | Usato per archiviare gli identificatori di oggetto per l'operazione in blocco. |
La funzione ReadContentPropertiesBulk nel modulo ContentProperties.cpp dell'applicazione di esempio illustra un'operazione di recupero bulk.
La prima attività eseguita in questo esempio determina se il driver specificato supporta le operazioni bulk. Questa operazione viene eseguita chiamando QueryInterface sull'interfaccia IPortableDeviceProperties e verificando l'esistenza di 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");
}
}
Se il driver supporta operazioni bulk, il passaggio successivo consiste nel creare un'istanza dell'interfaccia IPortableDeviceKeyCollection e specificare le chiavi che corrispondono alle proprietà recuperate dall'applicazione. Per una descrizione di questo processo, vedere l'argomento Recupero delle proprietà per un singolo oggetto .
Dopo aver specificato le chiavi appropriate, l'applicazione di esempio crea un'istanza dell'interfaccia IPortableDevicePropertiesBulkCallback. L'applicazione userà i metodi in questa interfaccia per tenere traccia dello stato di avanzamento dell'operazione di recupero bulk asincrono.
if (SUCCEEDED(hr))
{
pCallback = new CGetBulkValuesCallback();
if (pCallback == NULL)
{
hr = E_OUTOFMEMORY;
printf("! Failed to allocate CGetBulkValuesCallback, hr = 0x%lx\n", hr);
}
}
La funzione successiva chiamata dall'applicazione di esempio è la funzione helper CreateIPortableDevicePropVariantCollectionWithAllObjectIDs. Questa funzione crea un elenco di tutti gli identificatori di oggetto disponibili a scopo di esempio. Un'applicazione reale limita l'elenco di identificatori a un determinato set di oggetti. Ad esempio, un'applicazione può creare un elenco di identificatori per tutti gli oggetti attualmente presenti in una determinata visualizzazione cartella.
Come indicato in precedenza, la funzione helper enumera in modo ricorsivo tutti gli oggetti in un determinato dispositivo. Restituisce questo elenco in un'interfaccia IPortableDevicePropVariantCollection che contiene un identificatore per ogni oggetto trovato. La funzione helper è definita nel modulo 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);
}
Una volta eseguiti i passaggi precedenti, l'applicazione di esempio avvia il recupero della proprietà asincrona. A tale scopo, eseguire le operazioni seguenti:
- Chiamata di IPortableDevicePropertiesBulk::QueueGetValuesByObjectList, che accoda una richiesta per il recupero della proprietà bulk. Si noti che, anche se la richiesta è in coda, non viene avviata.
- Chiamata di IPortableDevicePropertiesBulk::Start per avviare la richiesta in coda.
Questi passaggi sono illustrati nell'estratto di codice seguente dall'applicazione di esempio.
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);
}
}
Argomenti correlati