Udostępnij przez


Korzystanie z enumeratora urządzeń systemowych

[Funkcja skojarzona z tą stroną, DirectShow, jest starszą funkcją. Został zastąpiony przez MediaPlayer, IMFMediaEnginei Audio/Video Capture w Media Foundation. Te funkcje zostały zoptymalizowane pod kątem systemów Windows 10 i Windows 11. Microsoft mocno zaleca, aby nowy kod używał MediaPlayer, IMFMediaEngine i Audio/Video Capture w programie Media Foundation zamiast DirectShow, jeśli to możliwe. Firma Microsoft sugeruje, że istniejący kod, który używa starszych interfejsów API, należy przepisać go do korzystania z nowych interfejsów API, jeśli to możliwe.]

Moduł wyliczający urządzenia systemowego zapewnia jednolity sposób wyliczania według kategorii filtrów zarejestrowanych w systemie użytkownika. Ponadto rozróżnia poszczególne urządzenia sprzętowe, nawet jeśli ten sam filtr je obsługuje. Jest to szczególnie przydatne w przypadku urządzeń korzystających z modelu sterowników systemu Windows (WDM) i filtru KSProxy. Na przykład użytkownik może mieć kilka urządzeń do przechwytywania wideo WDM, które są obsługiwane przez ten sam filtr. Moduł wyliczający urządzenia systemowe traktuje je jako oddzielne wystąpienia urządzeń.

Wyliczarka urządzeń systemowych działa poprzez utworzenie wyliczarki dla określonej kategorii, takiej jak przechwytywanie dźwięku lub kompresja wideo. Moduł wyliczający kategorii zwraca unikatową nazwę dla każdego urządzenia w kategorii. Moduł wyliczający kategorii automatycznie uwzględnia wszystkie odpowiednie urządzenia Plug and Play w kategorii. Aby uzyskać listę kategorii, zobacz Filter Categories.

Aby użyć modułu wyliczającego urządzenia systemowego, wykonaj następujące czynności:

  1. Utwórz enumerator urządzeń systemowych, wywołując CoCreateInstance. Identyfikator klasy (CLSID) jest CLSID_SystemDeviceEnum.
  2. Uzyskaj moduł wyliczający kategorii, wywołując ICreateDevEnum::CreateClassEnumerator za pomocą identyfikatora CLSID żądanej kategorii. Ta metoda zwraca wskaźnik interfejsu IEnumMoniker. Jeśli kategoria jest pusta (lub nie istnieje), metoda zwraca S_FALSE, a nie kod błędu. Jeśli tak, zwrócony wskaźnik IEnumMoniker jest NULL i wyłuszczenie go spowoduje wyjątek. W związku z tym jawnie przetestuj S_OK podczas wywoływania createClassEnumeratorzamiast wywoływania zwykłego makra SUCCEEDED.
  3. Użyj metody IEnumMoniker::Next, aby wyliczyć każdy moniker. Ta metoda zwraca wskaźnik interfejsu IMoniker. Gdy metoda Next osiągnie koniec wyliczenia, zwraca również S_FALSE, więc ponownie sprawdź S_OK.
  4. Aby pobrać przyjazną nazwę urządzenia (na przykład do wyświetlenia w interfejsie użytkownika), wywołaj metodę IMoniker::BindToStorage.
  5. Aby utworzyć i zainicjować filtr DirectShow, który zarządza urządzeniem, należy wywołać IMoniker::BindToObject na monikerze. Wywołaj IFilterGraph::AddFilter, aby dodać filtr do grafu.

Na poniższym diagramie przedstawiono ten proces.

wyliczanie urządzeń

W poniższym przykładzie pokazano, jak wyliczyć kompresory wideo zainstalowane w systemie użytkownika. Dla zwięzłości przykład przeprowadza minimalne sprawdzanie błędów.

// 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();

Nazwy Urządzeń

Dla nazw urządzeń można przekazać nazwę do metody IFilterGraph2::AddSourceFilterForMoniker, aby utworzyć filtr przechwytywania dla urządzenia. Na przykład kod można znaleźć w dokumentacji tej metody.

Metoda IMoniker::GetDisplayName zwraca nazwę wyświetlaną znacznika. Chociaż nazwa wyświetlana jest czytelna, zazwyczaj nie jest wyświetlana użytkownikowi końcowemu. Pobierz przyjazną nazwę z zestawu właściwości, zgodnie z wcześniejszym opisem.

Metody IMoniker::ParseDisplayName lub funkcji MkParseDisplayName można użyć do utworzenia domyślnego monikera urządzenia dla danej kategorii filtra. Użyj nazwy wyświetlanej w formacie @device:*:{category-clsid}, gdzie category-clsid jest tekstową reprezentacją identyfikatora GUID kategorii. Domyślną nazwą jest pierwszy moniker zwrócony przez enumerator urządzeń dla tej kategorii.