QCroreApplication QApplication с WMI - PullRequest
6 голосов
/ 05 июня 2010

Я нашел несколько примеров приложений WMI C ++ на веб-сайте MSDN.

Я попробовал код формы по ссылке ниже

http://msdn.microsoft.com/en-us/library/aa390423%28v=VS.85%29.aspx

когда я скопировал и запустил приложение как консольное приложение win32, оно работало хорошо.

тот же код, который я выложил в приложение Qt,

Когда я использую QApplication anApplication (argc, argv); в моем коде это не работает

Но если я использую QCroreApplication anApplication (argc, argv); это работает

показывает мне ошибку типа "когда я изменяю QCroreApplication на QApplication Приведенный ниже исходный код не работает и выдает ошибку типа" Не удалось инициализировать библиотеку COM. Код ошибки = 0x80010106 "

Любые предложения или помощь

#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>

# pragma comment(lib, "wbemuuid.lib")

// Qt Includes
#include <QtCore>
#include <QtGui>


 //----------------------------------------------------------------------------

// Main Function
int main( int a_argc, char *a_argv[] )
//************************************
{
    // initialize the application
    QApplication anapplication( a_argc, a_argv );

    HRESULT hres;

    // Step 1: --------------------------------------------------
    // Initialize COM. ------------------------------------------

    hres =  CoInitializeEx(0, COINIT_MULTITHREADED); 
    if (FAILED(hres))
    {
        cout << "Failed to initialize COM library. Error code = 0x" 
            << hex << hres << endl;
        return 1;                  // Program has failed.
    }

    // Step 2: --------------------------------------------------
    // Set general COM security levels --------------------------
    // Note: If you are using Windows 2000, you need to specify -
    // the default authentication credentials for a user by using
    // a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
    // parameter of CoInitializeSecurity ------------------------

    hres =  CoInitializeSecurity(
        NULL, 
        -1,                          // COM authentication
        NULL,                        // Authentication services
        NULL,                        // Reserved
        RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication 
        RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
        NULL,                        // Authentication info
        EOAC_NONE,                   // Additional capabilities 
        NULL                         // Reserved
        );


    if (FAILED(hres))
    {
        cout << "Failed to initialize security. Error code = 0x" 
            << hex << hres << endl;
        CoUninitialize();
        return 1;                    // Program has failed.
    }

    // Step 3: ---------------------------------------------------
    // Obtain the initial locator to WMI -------------------------

    IWbemLocator *pLoc = NULL;

    hres = CoCreateInstance(
        CLSID_WbemLocator,             
        0, 
        CLSCTX_INPROC_SERVER, 
        IID_IWbemLocator, (LPVOID *) &pLoc);

    if (FAILED(hres))
    {
        cout << "Failed to create IWbemLocator object."
            << " Err code = 0x"
            << hex << hres << endl;
        CoUninitialize();
        return 1;                 // Program has failed.
    }

    // Step 4: -----------------------------------------------------
    // Connect to WMI through the IWbemLocator::ConnectServer method

    IWbemServices *pSvc = NULL;

    // Connect to the root\cimv2 namespace with
    // the current user and obtain pointer pSvc
    // to make IWbemServices calls.
    hres = pLoc->ConnectServer(
         _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
         NULL,                    // User name. NULL = current user
         NULL,                    // User password. NULL = current
         0,                       // Locale. NULL indicates current
         NULL,                    // Security flags.
         0,                       // Authority (e.g. Kerberos)
         0,                       // Context object 
         &pSvc                    // pointer to IWbemServices proxy
         );

    if (FAILED(hres))
    {
        cout << "Could not connect. Error code = 0x" 
             << hex << hres << endl;
        pLoc->Release();     
        CoUninitialize();
        return 1;                // Program has failed.
    }

    cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;


    // Step 5: --------------------------------------------------
    // Set security levels on the proxy -------------------------

    hres = CoSetProxyBlanket(
       pSvc,                        // Indicates the proxy to set
       RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
       RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
       NULL,                        // Server principal name 
       RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx 
       RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
       NULL,                        // client identity
       EOAC_NONE                    // proxy capabilities 
    );

    if (FAILED(hres))
    {
        cout << "Could not set proxy blanket. Error code = 0x" 
            << hex << hres << endl;
        pSvc->Release();
        pLoc->Release();     
        CoUninitialize();
        return 1;               // Program has failed.
    }

    // Step 6: --------------------------------------------------
    // Use the IWbemServices pointer to make requests of WMI ----

    // For example, get the name of the operating system
    IEnumWbemClassObject* pEnumerator = NULL;
    hres = pSvc->ExecQuery(
        bstr_t("WQL"), 
        bstr_t("SELECT * FROM Win32_USBControllerDevice"),
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
        NULL,
        &pEnumerator);

//ExecQuery(L"WQL", L"SELECT * FROM Win32_LogicalDisk", WBEM_FLAG_FORWARD_ONLY, NULL, &iter);

    if (FAILED(hres))
    {
        cout << "Query for operating system name failed."
            << " Error code = 0x" 
            << hex << hres << endl;
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        return 1;               // Program has failed.
    }

    // Step 7: -------------------------------------------------
    // Get the data from the query in step 6 -------------------

    IWbemClassObject *pclsObj;
    ULONG uReturn = 0;

    while (pEnumerator)
    {
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, 
            &pclsObj, &uReturn);

        if(FAILED(hr)||0 == uReturn)
        {
            break;
        }

        VARIANT vtProp;

        // Get the value of the Name property
        /*hr = pclsObj->Get(L"VolumeName", 0, &vtProp, 0, 0);
        wcout << " VolumeName : " << vtProp.bstrVal << endl;
        VariantClear(&vtProp);*/


        if (FAILED(pclsObj->Get(L"Antecedent", 0, &vtProp, 0, 0)))
        {
            cout<<"The specified property is not found."<<endl;
        }
        else
        {
            wcout <<vtProp.bstrVal << endl;
        }

        pclsObj->Release();
    }

    // Cleanup
    // ========

    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
   // pclsObj->Release();
    CoUninitialize();


   // return 0;   // Program successfully completed.

    //execute the application
    int anInt = anapplication.exec();

    return anInt;
}
//-----------------------------------------------------------------------------

Ответы [ 2 ]

5 голосов
/ 14 июня 2010

Ошибка, которую вы получаете, связана с тем, что COM уже инициализирован. QApplication вызывает OleInitialize в своем конструкторе, а QCoreApplication - нет, поэтому при использовании QApplication вы получаете ошибку 0x80010106 (RPC_E_CHANGED_MODE). Для дальнейшего чтения см. Документацию для CoInitializeEx . Следующая статья должна предоставить более глубокое понимание.

1 голос
/ 08 июля 2015

Сначала я использовал этот код

hres =  CoInitializeEx(0, COINIT_MULTITHREADED);

if (hres == RPC_E_CHANGED_MODE) {
    OleUninitialize();
    hres =  CoInitializeEx(0, COINIT_MULTITHREADED);
}

Когда я получаю сообщение об ошибке "Не удалось инициализировать библиотеку COM (0x80010106)

Я просто вызываю OleUninitialize для работы с OleInitialize () в QApplication, но это может нарушить некоторые функции qt.

Как я обнаружил, лучше всего использовать флаг COINIT_APARTMENTTHREADED для CoInitializeEx

1010 * MSDN *

Как правило, поток, который создает окно, должен использовать флаг COINIT_APARTMENTTHREADED, а другие потоки должны использовать COINIT_MULTITHREADED. Однако для некоторых компонентов COM требуется определенная модель потоков. Документация MSDN должна сообщить вам, когда это так.

Для меня это черная магия, но она мне помогла

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...