Почему CoCreateInstance возвращает REGDB_E_CLASSNOTREG в некоторых Windows? - PullRequest
0 голосов
/ 19 февраля 2019

Я хочу использовать DSound Audio Render в одном из моих приложений, поэтому я загружаю его с CoCreateInstance .Вот небольшой фрагмент:

#include <iostream>
#include <strmif.h>
#include <uuids.h>

int main()
{
    std::cout << "Start" << std::endl;

    HRESULT hr = CoInitialize(NULL);

    printf("CoInitialize = 0x%x\n", hr);

    IBaseFilter* ptr = NULL;
    hr = CoCreateInstance(CLSID_DSoundRender, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&ptr);

    printf("CoCreateInstance = 0x%x\n", hr);

    ptr->Release();

    CoUninitialize();

    std::cout << "End" << std::endl;

    std::cin.get();
}

Проблема в том, что в Windows, которую я использую для разработки своего приложения, оно работает хорошо, а hr всегда 0x0 (S_OK), но в Windowsмоего клиента выдает ошибку 0x0x80040154 (REGDB_E_CLASSNOTREG) при вызове CoCreateInstance.

Это 32-разрядное приложение, работающее в 64-разрядной версии Windows 10 (для разработчика) и в Windows Server 2016Центр обработки данных 64 бита (для продукта).

Я проверяю реестр, и соответствующая DLL (quartz.dll) правильно зарегистрирована.Действительно, я получаю эти результаты на обеих Windows:

PS C:\Users\pierre> Get-ChildItem -Path "Registry::HKCR\CLSID\{79376820-07D0-11CF-A24D-0020AFD79767}"


    Hive: HKCR\CLSID\{79376820-07D0-11CF-A24D-0020AFD79767}


Name                           Property
----                           --------
InprocServer32                 (default)      : C:\Windows\System32\quartz.dll
                               ThreadingModel : Both


PS C:\Users\pierre> Get-ChildItem -Path "Registry::HKCR\WOW6432Node\CLSID\{79376820-07D0-11CF-A24D-0020AFD79767}"


    Hive: HKCR\WOW6432Node\CLSID\{79376820-07D0-11CF-A24D-0020AFD79767}


Name                           Property
----                           --------
InprocServer32                 (default)      : C:\Windows\SysWOW64\quartz.dll
                               ThreadingModel : Both

PS C:\Users\pierre> dir C:\Windows\System32\quartz.dll


    Répertoire : C:\Windows\System32


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       15/09/2018     09:29        1639424 quartz.dll


PS C:\Users\pierre> dir C:\Windows\SysWOW64\quartz.dll


    Répertoire : C:\Windows\SysWOW64


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       15/09/2018     09:29        1470464 quartz.dll

Я также использовал procmon.exe, и все вызовы выглядят правильно.

Что я должен изменить в конфигурациимоего клиента, чтобы заставить его работать?

1 Ответ

0 голосов
/ 20 февраля 2019

MSDN объясняет в разделе «Замечания», как этот фильтр DirectShow должен участвовать в конвейерах графа DirectShow:

Этот фильтр действует как оболочка для аудиоустройство .Чтобы перечислить аудиоустройства, доступные в системе пользователя, используйте интерфейс ICreateDevEnum с категорией аудио рендеринга (CLSID_AudioRendererCategory).Для каждого аудиоустройства категория аудио рендерера содержит два экземпляра фильтра.Один из них соответствует DirectSound Renderer, а другой соответствует фильтру Audio Renderer (WaveOut).Экземпляр DirectSound имеет понятное имя «DirectSound: DeviceName», где DeviceName - это имя устройства.Экземпляр WaveOut имеет понятное имя DeviceName.

Обратите внимание, что обычно вы не должны создавать фильтр напрямую, используя CoCreateInstance, что вы делаете.Для этого есть веская причина: это объект-обертка, и ему обычно требуется контекст инициализации, который связывает его с конкретным устройством вывода звука.Выполняя прямую инициализацию, вы неявно указываете ему использовать устройство по умолчанию.

В системах без устройств вывода звука фильтр не видит устройств и может выдать сбой на раннем этапе создания экземпляра, что приведет к ошибке COM.Вы бы увидели регистрацию COM, но отсутствие аппаратного обеспечения и ранний отказ вызовут общую ошибку COM, а не специфичную для API.

Как правило, вы все равно должны предпочесть использование интерфейса ICreateDevEnum (как рекомендует MSDN), а не CoCreateInstance.

...