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

要解決很簡單,就是根據錯誤提示,不用初始化了,把代碼中的兩個初始化函數刪除就可以了

但是通過上述修改線程類型也可以解決


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM