为什么 CoCreateInstance 可以在完全相同的上下文中 return 两个不同的 HRESULT?

Why CoCreateInstance can return two different HRESULT in the exact same context?

我想使用DSound Audio Render in one of my application so I load it with CoCreateInstance. According to ,如果我没有安装音频硬件,CoCreateInstance可以returnREGDB_E_CLASSNOTREG。但是,如果我第二次调用 CoCreateInstance,我就没有相同的 HRESULT。这是一个小例子(要重现它,您应该在 Windows 的设备管理器中禁用所有音频设备):

#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);

    if(ptr)
        ptr->Release();

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

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

    if(ptr)
        ptr->Release();

    CoUninitialize();

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

    std::cin.get();
}

我得到这个结果:

Start
CoInitialize = 0x0
CoCreateInstance = 0x80040154
CoCreateInstance = 0x80040256
End

第一个错误码0x80040154对应REGDB_E_CLASSNOTREG所以和 I got in my previous question but the second error code 0x80040256 corresponds to VFW_E_NO_AUDIO_HARDWARE. According to MSDN一致:

VFW_E_NO_AUDIO_HARDWARE
0x80040256

Cannot play back the audio stream: no audio hardware is available, or the hardware is not supported.

那么为什么我第二次调用 CoCreateInstance 时才出现有意义的错误?我可以更改什么以在第一次调用时出现此错误?

如果您想要有记录且一致的行为,那么您不应该偷工减料并遵循建议的路线,这些路线是:Using the System Device Enumerator.

音频渲染器类别中的设备枚举将为您提供 "Default DirectSound Device" 的名字对象,然后您的 IMoniker::BindToObject 将产生有意义的 VFW_E_NO_AUDIO_HARDWARE(在第一次调用和后续调用时那些)。

您也可以在不编写代码的情况下看到这一点:您可以使用 GraphStudioNext 应用程序、菜单图形、插入过滤器、组合框中的 "Audio Renderers" 类别,然后双击 "Default DirectSound Device" 条目尝试实例化过滤器。

至于关于不同代码的标语问题,这是我有根据的猜测。错误代码最终来自软件。您有机会看到系统中存在 COM 服务器,因此 COM 子系统确实开始实例化,然后在中间失败并将失败代码转发给您。 COM 服务器很可能具有单例或缓存的硬件枚举。在您的第一次尝试中,它在初始化期间遇到 "no devices" 条件并在较早的步骤中止实例化,因此 COM 报告无法创建实例。下一次服务器已经看到其缓存的枚举(也就是说,它不是您假设的 "exactly the same context")并跳过初始故障点,但随后再次遇到下一次检查。

对此您无能为力,尤其是您应该首先以不同方式实例化 CLSID_DSoundRender