Abrufen von Eigenschaften für mehrere Objekte
Einige Gerätetreiber unterstützen das Abrufen von Eigenschaften für mehrere Objekte in einem einzigen Funktionsaufruf. Dies wird als Massenabruf bezeichnet. Es gibt zwei Arten von Massenabrufvorgängen: Der erste Typ ruft Eigenschaften für eine Liste von Objekten ab, und der zweite Typ ruft Eigenschaften für alle Objekte eines bestimmten Formats ab. Das in diesem Abschnitt beschriebene Beispiel veranschaulicht das erste Beispiel.
Ihre Anwendung kann einen Massenabruf über die in der folgenden Tabelle beschriebenen Schnittstellen ausführen.
Schnittstelle | Beschreibung |
---|---|
IPortableDeviceContent-Schnittstelle | Bietet Zugriff auf die inhaltsspezifischen Methoden. |
IPortableDeviceKeyCollection-Schnittstelle | Wird verwendet, um die abzurufenden Eigenschaften zu identifizieren. |
IPortableDeviceProperties-Schnittstelle | Wird verwendet, um zu bestimmen, ob ein bestimmter Treiber Massenvorgänge unterstützt. |
IPortableDevicePropertiesBulk-Schnittstelle | Unterstützt den Massenabrufvorgang. |
IPortableDevicePropVariantCollection-Schnittstelle | Dient zum Speichern der Objektbezeichner für den Massenvorgang. |
Die ReadContentPropertiesBulk-Funktion im ContentProperties.cpp-Modul der Beispielanwendung veranschaulicht einen Massenabrufvorgang.
Die erste In diesem Beispiel durchgeführte Aufgabe besteht darin, zu bestimmen, ob der angegebene Treiber Massenvorgänge unterstützt oder nicht. Dies wird erreicht, indem QueryInterface auf der IPortableDeviceProperties-Schnittstelle aufgerufen und überprüft wird, ob IPortableDevicePropertiesBulk vorhanden ist.
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");
}
}
Wenn der Treiber Massenvorgänge unterstützt, besteht der nächste Schritt darin, eine instance der IPortableDeviceKeyCollection-Schnittstelle zu erstellen und die Schlüssel anzugeben, die den Eigenschaften entsprechen, die von der Anwendung abgerufen werden. Eine Beschreibung dieses Prozesses finden Sie im Thema Abrufen von Eigenschaften für ein einzelnes Objekt .
Nachdem die entsprechenden Schlüssel angegeben wurden, erstellt die Beispielanwendung eine instance der IPortableDevicePropertiesBulkCallback-Schnittstelle. Die Anwendung verwendet die Methoden in dieser Schnittstelle, um den Fortschritt des asynchronen Massenabrufvorgangs nachzuverfolgen.
if (SUCCEEDED(hr))
{
pCallback = new CGetBulkValuesCallback();
if (pCallback == NULL)
{
hr = E_OUTOFMEMORY;
printf("! Failed to allocate CGetBulkValuesCallback, hr = 0x%lx\n", hr);
}
}
Die nächste Funktion, die von der Beispielanwendung aufgerufen wird, ist die Hilfsfunktion CreateIPortableDevicePropVariantCollectionWithAllObjectIDs. Diese Funktion erstellt eine Liste aller verfügbaren Objektbezeichner für Beispielzwecke. (Eine reale Anwendung würde die Liste der Bezeichner auf einen bestimmten Satz von Objekten beschränken. Für instance kann eine Anwendung eine Liste von Bezeichnern für alle Objekte erstellen, die sich derzeit in einer angegebenen Ordneransicht befinden.)
Wie bereits erwähnt, listet die Hilfsfunktion rekursiv alle Objekte auf einem bestimmten Gerät auf. Diese Liste wird in einer IPortableDevicePropVariantCollection-Schnittstelle zurückgegeben, die einen Bezeichner für jedes gefundene Objekt enthält. Die Hilfsfunktion ist im Modul ContentEnumeration.cpp definiert.
// 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);
}
Nachdem die vorherigen Schritte ausgeführt wurden, initiiert die Beispielanwendung den asynchronen Eigenschaftsabruf. Dies wird wie folgt erreicht:
- Aufrufen von IPortableDevicePropertiesBulk::QueueGetValuesByObjectList, das eine Anforderung für den Massenabruf der Eigenschaft in die Warteschlange stellt. (Beachten Sie, dass die Anforderung zwar in die Warteschlange eingereiht, aber nicht gestartet wird.)
- Aufrufen von IPortableDevicePropertiesBulk::Start, um die Anforderung in der Warteschlange zu initiieren.
Diese Schritte werden im folgenden Codeauszug aus der Beispielanwendung veranschaulicht.
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);
}
}
Zugehörige Themen