Device Collections Returned By Synchronous Searches
Device collections are objects that contain one or more Device objects. A Device collection exposes the IUPnPDevices interface that provides methods and properties for traversing the collection and extracting individual device objects.
VBScript Example
VBScript applications can access the objects in the collection in two ways. First, they can traverse the elements sequentially using a for … each ... next loop as shown in the following example:
for each deviceObj in devices
MsgBox(deviceObj.FriendlyName)
next
In this example, the devices variable is assumed to have been initialized with the result of a prior search. The loop steps through the Device objects in the collection, assigning the variable deviceObj the value of each Device object in turn. The body of the loop can contain code that processes the Device object.
C++ Example
The following example shows the C++ code required to access the objects in a collection of device objects. The function shown, TraverseCollection, receives a pointer to the IUPnPDevices interface as an input parameter. This interface pointer could be returned by the FindByType method, or other Find methods, of the Device Finder object.
#include <windows.h>
#include <upnp.h>
#pragma comment(lib, "oleaut32.lib")
HRESULT TraverseCollection(IUPnPDevices * pDevices)
{
IUnknown * pUnk = NULL;
HRESULT hr = pDevices->get__NewEnum(&pUnk);
if (SUCCEEDED(hr))
{
IEnumVARIANT * pEnumVar = NULL;
hr = pUnk->QueryInterface(IID_IEnumVARIANT, (void **) &pEnumVar);
if (SUCCEEDED(hr))
{
VARIANT varCurDevice;
VariantInit(&varCurDevice);
pEnumVar->Reset();
// Loop through each device in the collection
while (S_OK == pEnumVar->Next(1, &varCurDevice, NULL))
{
IUPnPDevice * pDevice = NULL;
IDispatch * pdispDevice = V_DISPATCH(&varCurDevice);
if (SUCCEEDED(pdispDevice->QueryInterface(IID_IUPnPDevice, (void **) &pDevice)))
{
// Do something interesting with pDevice
BSTR bstrName = NULL;
if (SUCCEEDED(pDevice->get_FriendlyName(&bstrName)))
{
OutputDebugStringW(bstrName);
SysFreeString(bstrName);
}
}
VariantClear(&varCurDevice);
pDevice->Release();
}
pEnumVar->Release();
}
pUnk->Release();
}
return hr;
}
The first step is to request a new enumerator for the collection using the _NewEnum property. This returns an enumerator as the IUnknown interface. The sample code invokes IUnknown::QueryInterface to obtain the IEnumVARIANT interface. The sample code then sets the enumerator to the beginning of the collection by invoking the IEnumVARIANT::Reset method. Finally, the sample code invokes the IEnumVARIANT::Next method to traverse the collection. The device objects in the collection are contained within VARIANT structures. These structures contain pointers to IDispatch interfaces on the device objects. To obtain the IUPnPDevice interface, the sample code invokes QueryInterface on the IDispatch interface.