Ejemplo: Obtener datos WMI del equipo local

Puede usar el procedimiento y los ejemplos de código de este tema para crear una aplicación cliente WMI completa que realice la inicialización COM, se conecte a WMI en el equipo local, obtenga datos de forma semiasincrónica y, a continuación, realice la limpieza. En este ejemplo se obtiene el nombre del sistema operativo en el equipo local y se muestra. Para recuperar datos de un equipo remoto, consulte Ejemplo: Obtener datos WMI desde un equipo remoto. Para obtener los datos de forma asincrónica, consulte Ejemplo: Obtener datos WMI del equipo local de forma asincrónica.

El siguiente procedimiento se usa para ejecutar la aplicación WMI. Los pasos del 1 al 5 contienen todos los pasos necesarios para configurar y conectarse a WMI, y los pasos 6 y 7 son donde se consultan y reciben los datos.

  1. Inicialice parámetros COM con una llamada a CoInitializeEx.

    Para obtener más información, consulte Inicializar COM para una aplicación WMI.

  2. Inicialice la seguridad del proceso COM mediante una llamada a CoInitializeSecurity.

    Para obtener más información, consulte Establecimiento del nivel de seguridad de proceso predeterminado mediante C++.

  3. Obtenga el localizador inicial de WMI mediante una llamada a CoCreateInstance.

    Para obtener más información, consulte Crear una conexión a un espacio de nombres WMI.

  4. Obtenga un puntero a IWbemServices para el espacio de nombres root\cimv2 en el equipo local llamando a IWbemLocator::ConnectServer. Para conectarse a un equipo remoto, consulte Ejemplo: Obtener datos WMI desde un equipo remoto.

    Para obtener más información, consulte Crear una conexión a un espacio de nombres WMI.

  5. Establezca la seguridad del proxy IWbemServices para que el servicio WMI pueda suplantar al cliente llamando a CoSetProxyBlanket.

    Para obtener más información, consulte Establecer los niveles de seguridad en una conexión WMI.

  6. Use el puntero IWbemServices para realizar solicitudes de WMI. En este ejemplo se ejecuta una consulta para el nombre del sistema operativo mediante una llamada a IWbemServices::ExecQuery.

    La siguiente consulta WQL es uno de los argumentos del método.

    SELECT * FROM Win32_OperatingSystem

    El resultado de esta consulta se almacena en un puntero IEnumWbemClassObject. Esto permite que los objetos de datos de la consulta se recuperen de forma semisincrónica con la interfaz IEnumWbemClassObject. Para más información, consulte Enumeración de WMI. Para obtener los datos de forma asincrónica, consulte Ejemplo: Obtener datos WMI del equipo local de forma asincrónica.

    Para obtener más información sobre cómo realizar solicitudes a WMI, consulte Manipular información de clase e instancia, Consultar WMI y Llamar a un método.

  7. Obtener y mostrar los datos de la consulta WQL. El puntero IEnumWbemClassObject está vinculado a los objetos de datos que devuelve la consulta y los objetos de datos que se pueden recuperar con el método IEnumWbemClassObject::Next. Este método vincula los objetos de datos a un puntero IWbemClassObject que se pasa al método. Use el método IWbemClassObject::Get para obtener la información deseada de los objetos de datos.

    El siguiente ejemplo de código se usa para obtener la propiedad Name del objeto de datos, que proporciona el nombre del sistema operativo.

    VARIANT vtProp;
    VariantInit(&vtProp);
    // Get the value of the Name property
    hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);
    

    Después de almacenar el valor de la propiedad Name en la variable VARIANT vtProp, se puede mostrar al usuario.

    Para obtener más información, consulte Enumerar WMI.

En el ejemplo de código siguiente se recuperan datos WMI de forma semisincrónica desde un equipo local.

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

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

int main(int argc, char **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 --------------------------

    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 (for example, 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_OperatingSystem"),
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
        NULL,
        &pEnumerator);
    
    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 = NULL;
    ULONG uReturn = 0;
   
    while (pEnumerator)
    {
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, 
            &pclsObj, &uReturn);

        if(0 == uReturn)
        {
            break;
        }

        VARIANT vtProp;

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

        pclsObj->Release();
    }

    // Cleanup
    // ========
    
    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    CoUninitialize();

    return 0;   // Program successfully completed.
 
}