Verwenden des Systemgeräteenumerators

[Das dieser Seite zugeordnete Feature DirectShow ist ein Legacyfeature. Es wurde von MediaPlayer, IMFMediaEngine und Audio/Video Capture in Media Foundation abgelöst. Diese Features wurden für Windows 10 und Windows 11 optimiert. Microsoft empfiehlt dringend, dass neuer Code mediaPlayer, IMFMediaEngine und Audio/Video Capture in Media Foundation anstelle von DirectShow verwendet, wenn möglich. Microsoft schlägt vor, dass vorhandener Code, der die Legacy-APIs verwendet, so umgeschrieben wird, dass nach Möglichkeit die neuen APIs verwendet werden.]

Der Systemgeräte-Enumerator bietet eine einheitliche Möglichkeit, die filter, die im System eines Benutzers registriert sind, nach Kategorie aufzulisten. Darüber hinaus wird zwischen einzelnen Hardwaregeräten unterschieden, auch wenn sie vom gleichen Filter unterstützt werden. Dies ist besonders nützlich für Geräte, die das Windows-Treibermodell (WDM) und den KSProxy-Filter verwenden. Beispielsweise kann der Benutzer über mehrere WDM-Videoaufnahmegeräte verfügen, die alle vom gleichen Filter unterstützt werden. Der Systemgeräteenumerator behandelt sie als separate Geräteinstanzen.

Der Systemgeräte-Enumerator erstellt einen Enumerator für eine bestimmte Kategorie, z. B. Audioaufnahme oder Videokomprimierung. Der Kategorieenumerator gibt einen eindeutigen Moniker für jedes Gerät in der Kategorie zurück. Der Kategorie-Enumerator enthält automatisch alle relevanten Plug-and-Play-Geräte in der Kategorie. Eine Liste der Kategorien finden Sie unter Filtern von Kategorien.

Gehen Sie wie folgt vor, um den Systemgeräteenumerator zu verwenden:

  1. Erstellen Sie den Systemgeräteenumerator, indem Sie CoCreateInstance aufrufen. Der Klassenbezeichner (CLSID) ist CLSID_SystemDeviceEnum.
  2. Rufen Sie einen Kategorieenumerator ab, indem Sie ICreateDevEnum::CreateClassEnumerator mit der CLSID der gewünschten Kategorie aufrufen. Diese Methode gibt einen IEnumMoniker-Schnittstellenzeiger zurück. Wenn die Kategorie leer ist (oder nicht vorhanden ist), gibt die Methode S_FALSE anstelle eines Fehlercodes zurück. Wenn ja, ist der zurückgegebene IEnumMoniker-ZeigerNULL , und das Dereferenzieren führt zu einer Ausnahme. Testen Sie daher explizit auf S_OK, wenn Sie CreateClassEnumerator aufrufen, anstatt das übliche SUCCEEDED-Makro aufzurufen.
  3. Verwenden Sie die IEnumMoniker::Next-Methode , um jeden Moniker aufzulisten. Diese Methode gibt einen IMoniker-Schnittstellenzeiger zurück. Wenn die Next-Methode das Ende der Enumeration erreicht, gibt sie auch S_FALSE zurück. Überprüfen Sie also erneut, ob S_OK.
  4. Rufen Sie die IMoniker::BindToStorage-Methode auf, um den Anzeigenamen des Geräts abzurufen (z. B. zur Anzeige auf der Benutzeroberfläche).
  5. Um den DirectShow-Filter zu erstellen und zu initialisieren, der das Gerät verwaltet, rufen Sie IMoniker::BindToObject für den Moniker auf. Rufen Sie IFilterGraph::AddFilter auf, um den Filter dem Diagramm hinzuzufügen.

Dieser Prozess wird anhand des folgenden Diagramms veranschaulicht.

Auflisten von Geräten

Im folgenden Beispiel wird gezeigt, wie sie die Videokompressoren auflisten, die auf dem System des Benutzers installiert sind. Aus Gründen der Kürze führt das Beispiel eine minimale Fehlerüberprüfung durch.

// Create the System Device Enumerator.
HRESULT hr;
ICreateDevEnum *pSysDevEnum = NULL;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
    IID_ICreateDevEnum, (void **)&pSysDevEnum);
if (FAILED(hr))
{
    return hr;
}

// Obtain a class enumerator for the video compressor category.
IEnumMoniker *pEnumCat = NULL;
hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoCompressorCategory, &pEnumCat, 0);

if (hr == S_OK) 
{
    // Enumerate the monikers.
    IMoniker *pMoniker = NULL;
    ULONG cFetched;
    while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
    {
        IPropertyBag *pPropBag;
        hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, 
            (void **)&pPropBag);
        if (SUCCEEDED(hr))
        {
            // To retrieve the filter's friendly name, do the following:
            VARIANT varName;
            VariantInit(&varName);
            hr = pPropBag->Read(L"FriendlyName", &varName, 0);
            if (SUCCEEDED(hr))
            {
                // Display the name in your UI somehow.
            }
            VariantClear(&varName);

            // To create an instance of the filter, do the following:
            IBaseFilter *pFilter;
            hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,
                (void**)&pFilter);
            // Now add the filter to the graph. 
            //Remember to release pFilter later.
            pPropBag->Release();
        }
        pMoniker->Release();
    }
    pEnumCat->Release();
}
pSysDevEnum->Release();

Gerätemoniker

Bei Gerätemonikern können Sie den Moniker an die IFilterGraph2::AddSourceFilterForMoniker-Methode übergeben, um einen Erfassungsfilter für das Gerät zu erstellen. Beispielcode finden Sie in der Dokumentation zu dieser Methode.

Die IMoniker::GetDisplayName-Methode gibt den Anzeigenamen des Monikers zurück. Obwohl der Anzeigename lesbar ist, würden Sie ihn normalerweise nicht einem Endbenutzer anzeigen. Rufen Sie stattdessen den Anzeigenamen wie zuvor beschrieben aus dem Eigenschaftenbehälter ab.

Die IMoniker::P arseDisplayName-Methode oder die MkParseDisplayName-Funktion kann verwendet werden, um einen Standardgerätemoniker für eine bestimmte Filterkategorie zu erstellen. Verwenden Sie einen Anzeigenamen mit dem Format @device:*:{category-clsid}, wobei category-clsid die Zeichenfolgendarstellung der Kategorie-GUID ist. Der Standardmoniker ist der erste Moniker, der vom Geräteenumerator für diese Kategorie zurückgegeben wird.