【问题标题】:Why CoCreateInstance returns REGDB_E_CLASSNOTREG on some Windows?为什么 CoCreateInstance 在某些 Windows 上返回 REGDB_E_CLASSNOTREG?
【发布时间】:2019-02-19 18:01:12
【问题描述】:

我想在我的一个应用程序中使用DSound Audio Render,所以我用CoCreateInstance 加载它。这是一个小sn-p:

#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 位应用程序,在 Windows 10 64 位(开发版)和 Windows Server 2016 Datacenter 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,每次调用看起来都是正确的。

我应该对客户端的配置进行哪些更改才能使其正常工作?

【问题讨论】:

  • "我检查了注册表并且相应的 DLL (quartz.dll) 已正确注册" - 显然不是,否则CoCreateInstance() 不会抱怨缺少注册.您使用的是 Windows 32 位还是 64 位?你的应用是 32 位还是 64 位?顺便说一句,如果CoCreateInstance() 确实成功了,您的代码就会发生内存泄漏。您需要将void* ptr 更改为IBaseFilter* ptr,然后在使用完毕后调用ptr-&gt;Release(),然后再调用CoUninitialize()
  • 我首先要看的是“像这样的东西的位数。您是在 32 位上编写并在 64 位上进行测试,反之亦然?您是否查找过 CLSID_DSoundRender 并验证 HKCR\ CLSID\{numeric equiv of CLSID_DSoundRender} 有一个指向正确文件的 Inprocserver32 键?
  • @RemyLebeau 我在原始帖子中回答了您的问题:应用程序是 32 位,主机是 64 位(Winodws 10 和 Windows Server 2016)。我还纠正了内存泄漏。
  • @JosephWillcoxson 我在原始帖子中回答了您的问题:CLSID 是 79376820-07D0-11CF-A24D-0020AFD79767 并且 InProcServer 键的默认值指向 DLL 的正确路径:C:\Windows\SysWOW64\quartz.dll。由procmon.exe确认。

标签: c++ audio com directshow windows-server-2016


【解决方案1】:

MSDN explains 在“备注”部分下此 DirectShow 过滤器应该如何参与 DirectShow 图形管道:

此过滤器充当音频设备的包装器。要枚举用户系统上可用的音频设备,请使用带有音频渲染器类别 (CLSID_AudioRendererCategory) 的 ICreateDevEnum 接口。对于每个音频设备,音频渲染器类别包含两个过滤器实例。其中一个对应于 DirectSound Renderer,另一个对应于 Audio Renderer (WaveOut) 过滤器。 DirectSound 实例具有友好名称“DirectSound: DeviceName”,其中 DeviceName 是设备的名称。 WaveOut 实例具有友好名称 DeviceName。

请注意,您通常不应该直接使用 CoCreateInstance 实例化过滤器,您正在执行的操作。这有一个很好的理由:它是一个包装对象,通常需要将其绑定到特定音频输出设备的初始化上下文。通过直接初始化,您隐含地指示它使用默认设备。

在没有音频输出设备的系统上,过滤器将看不到任何设备,并可能在早期实例化步骤中发出故障,从而导致 COM 错误。您会看到 COM 注册,但缺少硬件和早期故障会触发通用 COM 错误,而不是特定于 API。

一般来说,您应该仍然更喜欢使用ICreateDevEnum 接口(如MSDN 推荐的那样)而不是CoCreateInstance

【讨论】:

    猜你喜欢
    • 2020-12-28
    • 2015-07-15
    • 2012-04-18
    • 2016-09-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多