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
要解决很简单,就是根据错误提示,不用初始化了,把代码中的两个初始化函数删除就可以了
但是通过上述修改线程类型也可以解决