QT中使用CoInitializeEx

1 在使用winmm.lib 里边的MMDevice的时候,用于音频采集播放等操作,在使用控制台程序直接操作的时候是没问题的;但是转到QTCreator的时候,封装COM的Dll运行的时候CoinitializeEX 会报错,80010106.

这里边找到一篇博客:

CoInitializeEx 
在GUI程序中,不再是这样:

hres = CoInitializeEx(0, COINIT_MULTITHREADED);


hres = CoInitializeEx(0, COINIT_APARTMENTTHREADED);

 

CoInitialize与CoInitializeEx的区别: 
CoInitialize指明以单线程方式创建。 
CoInitializeEx可以指定COINIT_MULTITHREADED以多线程方式创建。 
创建单线程方式的COM服务器时不用考虑串行化问题,多线程COM服务器就要考虑。 
在使用中,使用CoInitialize创建可使对象直接与线程连接,得到最高的性能。创建多线程对象可以直接接收所有线程的调用,不必像单线程那样需要消息排队,但却需要COM创建线程间汇集代理,这样访问效率不高。

CoInitializeSecurity返回RPC_E_TOO_LATE也是正确 
你会发现CoInitializeSecurity返回的不是想要的,是一个特别大的负数,但是转换为十六进制为0x80010119

这时候发现0x80010119就是RPC_E_TOO_LATE 
因此我们需要修改代码:

    if (FAILED(hres))
    {
        qDebug() << "Failed to initialize security. "
                 << "Error code = 0x"
                 << hex << hres << endl;
        CoUninitialize();
        return "";
    }

修改为:

    if ((hres != RPC_E_TOO_LATE) && FAILED(hres))
    {
        qDebug() << "Failed to initialize security. "
                 << "Error code = 0x"
                 << hex << hres << endl;
        CoUninitialize();
        return "";
    }

调用函数ExecQuery时,编译报错 
错误为: 
error: undefined reference to `_com_util::ConvertStringToBSTR(char const*)@4

因此我们需要正确的方式从QString转到BSTR,因此修改代码: 
由:

    hres = pSvc->ExecQuery(
    bstr_t("WQL"),
    bstr_t("SELECT * FROM Win32_VideoController"),
    WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    NULL,
    &pEnumerator);

改为:

    BSTR sql = SysAllocString(L"SELECT * FROM Win32_VideoControlle");
    BSTR wql = SysAllocString(L"WQL");

    hres = pSvc->ExecQuery(wql,
                           sql,
                           WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
                           NULL,
                           &pEnumerator);

这里用到了SysAllocString 
SysAllocString函数说明: 
This function allocates a new string and copies the passed string into it.

Next函数的返回值正确,但是uReturn等于0 
到最后,我们使用了Next进行查询,但是发现该函数的返回值hres是正确的,uReturn始终为0

hres = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);

完全是自己马虎造成,不知道细心的您发现了没有上面的代码:

BSTR sql = SysAllocString(L"SELECT * FROM Win32_VideoControlle");

再看一下,是不是SQL语句的拼写错误。

果然,Win32_VideoControlle错误了,应该是Win32_VideoController

修正为:

BSTR sql = SysAllocString(L"SELECT * FROM Win32_VideoController");
————————————————
转载---本文为CSDN博主「江南-一苇渡江」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文

 

原因:

 

COM代码被放到了DLL中被调用--转载自博客园:

因为加载DLL的时候会自动初始化COM库。所以再初始化就会报错,返回错误码:0x80010106 ----- Cannot change thread mode after it is set

要解决很简单,就是根据错误提示,不用初始化了,把代码中的两个初始化函数删除就可以了

但是通过上述修改线程类型也可以解决

posted on 2021-05-21 15:07  邗影  阅读(1178)  评论(0编辑  收藏  举报

导航