C++编译器WMI:无效查询

C++ Builder WMI : Invalid Query

本文关键字:无效 查询 WMI 编译器 C++      更新时间:2023-10-16

使用C++Builder XE4,我正在尝试读取Win32_DiskDrive信息,但没有成功。

    UnicodeString s;
    Variant vX, vY, vZ, vi;
    vX = Variant::CreateObject(L"WbemScripting.SWbemLocator");
    vY = vX.OleFunction(L"ConnectServer");
    vZ = vY.OleFunction(L"ExecQuery", L"SELECT * FROM Win32_DiskDrive");
    int n = vZ.OlePropertyGet(L"Count");  // Error
    s.SetLength(0);
    for (int i = 0; i < n; i++) {
        vi = vZ.OleFunction<int>(L"ItemIndex", i);
        s = vi.OlePropertyGet(L"Caption");
        RichEdit1->Lines->Add(s);
    }

我在收到错误消息"无效查询"

    int n = vZ.OlePropertyGet(L"Count");  // Error

当我检查vZ时,IDE显示"{{}}"。这是否意味着我在获取vZ或之前的某个地方犯了错误?

我的环境是Windows7专业版。

对上述代码的任何更正都将有所帮助。

从C++访问WMI最常见的方法是直接使用WMI COM客户端(wbemcli.h)。

试试这个例子。

#pragma hdrstop
#include <iostream>
using namespace std;
#include <wbemcli.h>
#include <comdef.h> 
#pragma argsused
int main(int argc, char* argv[])
{
    BSTR strNetworkResource;
    strNetworkResource = L"\\.\root\CIMV2";
    // Initialize COM. ------------------------------------------
    HRESULT hres;
    hres =  CoInitializeEx(0, COINIT_MULTITHREADED);
    if (FAILED(hres))
    {
        cout << "Failed to initialize COM library. Error code = 0x" << hex << hres << endl;
        cout << _com_error(hres).ErrorMessage() << endl;
        cout << "press enter to exit" << endl;
        cin.get();      
        return 1;                  // Program has failed.
    }
    // Set general COM security levels --------------------------

        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;
        cout << _com_error(hres).ErrorMessage() << endl;
        CoUninitialize();
        cout << "press enter to exit" << endl;
        cin.get();      
        return 1;                    // Program has failed.
    }
    // 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;
        cout << _com_error(hres).ErrorMessage() << endl;
        CoUninitialize();       
        cout << "press enter to exit" << endl;
        cin.get();      
        return 1;                 // Program has failed.
    }
    // Connect to WMI through the IWbemLocator::ConnectServer method
    IWbemServices *pSvc = NULL;

    hres = pLoc->ConnectServer(
         strNetworkResource,      // 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;    
        cout << _com_error(hres).ErrorMessage() << endl;
        pLoc->Release();
        CoUninitialize();
        cout << "press enter to exit" << endl;
        cin.get();          
        return 1;                // Program has failed.
    }
    cout << "Connected to root\CIMV2 WMI namespace" << endl;
    // 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;
        cout << _com_error(hres).ErrorMessage() << endl;
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        cout << "press enter to exit" << endl;
        cin.get();      
        return 1;               // Program has failed.
    }
    // Use the IWbemServices pointer to make requests of WMI ----
    IEnumWbemClassObject* pEnumerator = NULL;
    hres = pSvc->ExecQuery( L"WQL", L"SELECT * FROM Win32_DiskDrive",
    WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
    if (FAILED(hres))
    {
        cout << "ExecQuery failed" << " Error code = 0x"    << hex << hres << endl;
        cout << _com_error(hres).ErrorMessage() << endl;
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        cout << "press enter to exit" << endl;
        cin.get();      
        return 1;               // Program has failed.
    }

    // Get the data from the WQL sentence
    IWbemClassObject *pclsObj = NULL;
    ULONG uReturn = 0;
    while (pEnumerator)
    {
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
        if(0 == uReturn || FAILED(hr))
          break;
        VARIANT vtProp;
                hr = pclsObj->Get(L"Caption", 0, &vtProp, 0, 0);// String
                if (!FAILED(hr))
                {
                  if ((vtProp.vt==VT_NULL) || (vtProp.vt==VT_EMPTY))
                    wcout << "Caption : " << ((vtProp.vt==VT_NULL) ? "NULL" : "EMPTY") << endl;
                  else
                  if ((vtProp.vt & VT_ARRAY))
                    wcout << "Caption : " << "Array types not supported (yet)" << endl;
                  else
                    wcout << "Caption : " << vtProp.bstrVal << endl;
                }
                VariantClear(&vtProp);
                hr = pclsObj->Get(L"DeviceID", 0, &vtProp, 0, 0);// String
                if (!FAILED(hr))
                {
                  if ((vtProp.vt==VT_NULL) || (vtProp.vt==VT_EMPTY))
                    wcout << "DeviceID : " << ((vtProp.vt==VT_NULL) ? "NULL" : "EMPTY") << endl;
                  else
                  if ((vtProp.vt & VT_ARRAY))
                    wcout << "DeviceID : " << "Array types not supported (yet)" << endl;
                  else
                    wcout << "DeviceID : " << vtProp.bstrVal << endl;
                }
                VariantClear(&vtProp);

        pclsObj->Release();
        pclsObj=NULL;
    }
    // Cleanup
    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    if (pclsObj!=NULL)
     pclsObj->Release();
    CoUninitialize();
    cout << "press enter to exit" << endl;
    cin.get();
    return 0;   // Program successfully completed.
}

注意:如果您是从C++与WMI交互的新手,您可以使用WMI Delphi Code Creator,它可以帮助您探索WMI属性并创建访问WMI的C++代码。

我想,如果你让代码看起来更友好一点,那将有所帮助:

UnicodeString s;
Variant vX, vY, vZ, vi;
vX = Variant::CreateObject(L"WbemScripting.SWbemLocator");
vY = vX.OleFunction(L"ConnectServer");
vZ = vY.OleFunction(L"ExecQuery", L"SELECT * FROM Win32_DiskDrive");
int n = vZ.OlePropertyGet(L"Count");  // Error
s.SetLength(0);
for (int i = 0; i < n; i++) {
    vi = vZ.OleFunction<int>(L"ItemIndex", i);
    s = vi.OlePropertyGet(L"Caption");
    RichEdit1->Lines->Add(s);
}

试试这个:

RichEdit1->Lines->Clear();
Variant l = Variant::CreateObject("WbemScripting.SWbemLocator");
Variant svc = l.OleFunction("ConnectServer");
Variant objs = svc.OleFunction("ExecQuery", OleVariant("SELECT * FROM Win32_DiskDrive"));
Variant n = objs.OlePropertyGet("Count");  // Error
for (int i = 0; i < n; i++)
{
    Variant obj = objs.OleFunction<int>("ItemIndex", OleVariant(i));
    Variant props = obj.OlePropertyGet("Properties_");
    Variant prop = props.OleFunction("Item", OleVariant("Caption"));
    String Value = prop.OlePropertyGet("Value");
    RichEdit1->Lines->Add(Value);
}