2010-06-05 3 views
4

MSDN 웹 사이트에서 일부 WMI C++ 응용 프로그램 예제를 발견했습니다. 내가 복사하고 잘 작동 Win32 콘솔 응용 프로그램으로 응용 프로그램을 실행할 때QCroreApplication QApplication with WMI

나는 코드 형태를 아래의 링크

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

을 시도했습니다.

제가 Qt의 애플리케이션에 유타 동일한 코드

제가 의 QApplication anApplication 사용할 때 (는 argc, ARGV); 내 코드에서 작동하지 않습니다

하지만 QCroreApplication을 사용하는 경우 응용 프로그램 (argc, argv); 그것은 작동 중입니다

"나는 QApplication으로 QCroreApplication을 변경할 때 아래와 같은 오류가 발생합니다. 아래의 소스 코드가 작동하지 않고"COM 라이브러리를 초기화하지 못했습니다. "와 같은 오류가 발생합니다. 오류 코드 = 0x80010106 "

어떤 제안 또는 그 그래서 받고있는 오류가 COM 이미 초기화되기 때문입니다.의 QApplication은 생성자에서 OleInitialize를 호출하지만, QCoreApplication하지 않는

#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; 
} 
//----------------------------------------------------------------------------- 

답변

4

도움 당신은 당신의 QApplication을 사용하는 오류 0x80010106 (RPC_E_CHANGED_MODE)을받을 이유. 추가 읽기를 들어, CoInitializeEx의 설명서를 참조하십시오. 다음 article 더 많은 통찰력을 제공한다.

0

을 처음에 나는이 코드

를 사용했다
hres = CoInitializeEx(0, COINIT_MULTITHREADED); 

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

내가 오류가 때 "나는 단지의 QApplication에서 OleInitialize를()를 다루는 OleUninitialize를 호출

COM 라이브러리 (0x80010106)를 초기화하지 못했습니다하지만 일부 QT 기능을 깰 수 있습니다. 내가 최고의 발견으로

일반적으로

MSDN

의 COINIT_APARTMENTTHREADED 플래그를 사용한다 창을 생성하는 스레드

CoInitializeEx에서

에 대한 플래그 COINIT_APARTMENTTHREADED을 사용하는 것입니다, 그리고 다른 스레드가 COINIT_MULTITHREADED를 사용해야합니다. 그러나 일부 COM 구성 요소에는 특정 스레딩 모델이 필요합니다. 이 경우 MSDN 설명서에서 알려야합니다.

나를 위해 그것은 흑 마술이지만 도움이되었습니다.