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
要解決很簡單,就是根據錯誤提示,不用初始化了,把代碼中的兩個初始化函數刪除就可以了
但是通過上述修改線程類型也可以解決
