Enumeración de WMI

La enumeración es el acto de desplazarse por un conjunto de objetos y, posiblemente, modificar cada objeto a medida que avanza. Por ejemplo, puede enumerar un conjunto de objetos Win32_DiskDrive para buscar un número de serie determinado. Tenga en cuenta que, aunque puede enumerar cualquier objeto, WMI solo devuelve los objetos a los que usted tiene acceso de seguridad.

Las enumeraciones de grandes conjuntos de datos pueden requerir una gran cantidad de recursos y degradar el rendimiento. Para obtener más información, vea Mejora del rendimiento de la enumeración. También puede solicitar datos con una consulta más específica. Para obtener más información, vea Consulta de WMI.

En este tema se describen las secciones siguientes:

Enumeración de WMI mediante PowerShell

Si no conoce la ruta de acceso del objeto para una instancia en concreto o quiere recuperar todas las instancias de una clase específica, use Get-WmiObject con el nombre de la clase en el parámetro -class. Si quiere usar una consulta, puede usar el parámetro -query.

En el procedimiento siguiente se describe cómo enumerar las instancias de una clase mediante PowerShell.

Procedimiento para enumerar las instancias de una clase mediante PowerShell

  1. Enumere las instancias con una llamada al cmdlet Get-WmiObject.

    Get-WmiObject devuelve una colección de uno o varios objetos de WMI, los cuales puede enumerar. Para obtener más información, vea Acceso a una colección.

    Si quiere recuperar una instancia de clase WMI en otro espacio de nombres o en otro equipo, especifique el equipo y el espacio de nombres en los parámetros -computer y -namespace, respectivamente. Para obtener más información, vea Creación de un script de WMI. Esto solo funciona si tiene los privilegios de acceso adecuados. Para obtener más información, vea Mantenimiento de la seguridad de WMI y Ejecución de operaciones con privilegios.

  2. Recupere todas las instancias individuales que quiera usando los miembros de la colección.

El ejemplo de código siguiente recupera una colección de PowerShell y muestra la propiedad size para todas las instancias de unidades lógicas en el equipo local.

$objCol = get-wmiobject -class "Win32_LogicalDisk"

# Or, alternately
#$objCol = get-wmiobject -Query "SELECT * FROM Win32_LogicalDisk"

foreach ($Drive in $objCol)
{
    if ($Drive.size -ne $null)
    { "Drive " + $Drive.deviceID + " contains " + $Drive.size + " bytes" }
    else
    { "Drive " + $Drive.deviceID + " is not available." }
}

Enumeración de WMI mediante C# (Microsoft.Management.Infrastructure)

  1. Agregue una referencia al ensamblado de referencia Microsoft.Management.Infrastructure. (Este ensamblado se proporciona como parte del Kit de desarrollo de software (SDK) de Windows para Windows 8).
  2. Agregue una instrucción using para el espacio de nombres Microsoft.Management.Infrastructure.
    using Microsoft.Management.Infrastructure;
  1. Cree una instancia de un objeto CimSession. En el fragmento de código siguiente se usa el valor estándar "localhost" para el método CimSession.Create.
    CimSession cimSession = CimSession.Create("localhost");
  1. Llame al método CimSession.QueryInstances pasando el espacio de nombres de CIM y la consulta WQL deseados que se van a usar. El fragmento de código siguiente devolverá dos instancias que representan dos procesos estándar de Windows donde la propiedad handle (que representa un identificador de proceso, o PID) tiene un valor 0 o 4.
    IEnumerable<CimInstance> queryInstances =     
      cimSession.QueryInstances(@"root\cimv2", 
                                "WQL", 
                                @"select name from win32_process where handle = 0 or handle = 4");
  1. Recorra los objetos CimInstance devueltos.
    foreach (CimInstance cimInstance in enumeratedInstances)
    { 
      Console.WriteLine("Process name: {0}", cimInstance.CimInstanceProperties["Name"].Value);  
    }

En el ejemplo de código siguiente se enumeran todas las instancias de la clase Win32_Process (que representa los procesos activos) en la máquina local y se imprime el nombre de cada proceso.

Nota

En una aplicación real, definiría como parámetros el nombre del equipo ("localhost") y el espacio de nombres de CIM ("root\cimv2"). No obstante, en este ejemplo se han codificado de forma rígida para mayor simplicidad.

 

using System;
using System.Collections.Generic;
using Microsoft.Management.Infrastructure;

public partial class MI
{
    static void PrintCimInstance(CimInstance cimInstance)
    {
        Console.ForegroundColor = ConsoleColor.Blue;
        Console.WriteLine("{0} properties", cimInstance.CimSystemProperties.ClassName);
        Console.ResetColor();

        Console.WriteLine(String.Format("{0,-5}{1,-30}{2,-15}{3,-10}", 
                                        "Key?", "Property", "Type", "Value"));

        foreach (var enumeratedProperty in cimInstance.CimInstanceProperties)
        {
            bool isKey = ((enumeratedProperty.Flags & CimFlags.Key) == CimFlags.Key);

            if (enumeratedProperty.Value != null)
            {
                Console.WriteLine(
                    "{0,-5}{1,-30}{2,-15}{3,-10}",
                    isKey == true ? "Y" : string.Empty,
                    enumeratedProperty.Name,
                    enumeratedProperty.CimType,
                    enumeratedProperty.Value);
            }
        }
        Console.WriteLine();
    }

    public static void QueryInstance(string query)
    {
        try
        {
            CimSession cimSession = CimSession.Create("localhost");

            IEnumerable<CimInstance> queryInstances = 
              cimSession.QueryInstances(@"root\cimv2", "WQL", query);
            foreach (CimInstance cimInstance in queryInstances)
            {
                //Use the current instance. This example prints the instance. 
                PrintCimInstance(cimInstance);
            }
        }
         catch (CimException ex) 
        { 
            // Handle the exception as appropriate.
            // This example prints the message.
            Console.WriteLine(ex.Message); 
        }
    }
}

using System;

namespace MIClientManaged
{
    class Program
    {
        static void Main(string[] args)
        {
            while (true)
            {
                Console.Write(&quot;Enter WQL (x = Quit): &quot;);
                string query = Console.ReadLine().ToUpper();
                if (query.CompareTo(&quot;X&quot;) == 0) break;
                MI.QueryInstance(query);
            }
        }
    }
}

Enumeración de WMI mediante C# (System.Management)

Si no conoce la ruta de acceso del objeto para una instancia en concreto o quiere recuperar todas las instancias de una clase específica, use el objeto ManagementClass para recuperar una clase ManagementObjectCollection que contenga todas las instancias de una clase determinada en el espacio de nombres de WMI. Como alternativa, puede enviar una consulta a WMI con ManagementObjectSearcher para obtener el mismo conjunto de objetos.

Nota

System.Management era el espacio de nombres de .NET original que se usaba para acceder a WMI; sin embargo, las API de este espacio de nombres suelen ser más lentas y no se escalan tan bien como sus homólogos más modernos Microsoft.Management.Infrastructure.

 

En el procedimiento siguiente se describe cómo enumerar las instancias de una clase mediante C#.

Procedimiento para enumerar las instancias de una clase mediante C#

  1. Enumere las instancias con una llamada a ManagementClass.GetInstances.

    El método GetInstances devuelve una colección o un conjunto de objetos que se pueden enumerar. Para obtener más información, vea Acceso a una colección. La colección devuelta es realmente un objeto ManagementObjectCollection, por lo que se puede llamar a cualquiera de los métodos de ese objeto.

    Si quiere recuperar una instancia de clase WMI en otro espacio de nombres o en otro equipo, especifique el equipo y el espacio de nombres en el parámetro path. Para obtener más información, vea Creación de un script de WMI. Esto solo funciona si tiene los privilegios de acceso adecuados. Para obtener más información, vea Mantenimiento de la seguridad de WMI y Ejecución de operaciones con privilegios.

  2. Recupere todas las instancias individuales que quiera usando los miembros de la colección.

El ejemplo de código siguiente recupera una colección de C# y muestra la propiedad size para todas las instancias de unidades lógicas en el equipo local.

using System.Management;
...

ManagementClass mc = new ManagementClass("Win32_LogicalDisk");
ManagementObjectCollection objCol = mc.GetInstances();

//or, alternately
//ManagementObjectSearcher mgmtObjSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_LogicalDisk");
//ManagementObjectCollection objCol = mgmtObjSearcher.Get();

if (objCol.Count != 0)
{
   foreach (ManagementObject Drive in objCol)
   {
      if (Drive["size"] != null)
      {
         Console.WriteLine("Drive {0} contains {1} bytes.", Drive["deviceID"], Drive["size"]);
      }
      else
      {
         Console.WriteLine("Drive {0} is not available.", Drive["deviceID"]);
      }
   }
}
Console.ReadLine();

Enumeración de WMI mediante VBScript

Si no conoce la ruta de acceso del objeto para una instancia en concreto o quiere recuperar todas las instancias de una clase específica, use el método SWbemServices.InstancesOf para devolver una enumeración SWbemObjectSet de todas las instancias de una clase. Como alternativa, puede enviar una consulta a WMI con SWbemServices.ExecQuery para obtener el mismo conjunto de objetos.

En el procedimiento siguiente se describe cómo enumerar las instancias de una clase mediante VBScript.

Procedimiento para enumerar las instancias de una clase mediante VBScript

  1. Enumere las instancias con una llamada al método SWbemServices.InstancesOf.

    El método InstancesOf devuelve una colección o un conjunto de objetos que se pueden enumerar. Para obtener más información, vea Acceso a una colección. La colección devuelta es realmente un objeto SWbemObjectSet, por lo que se puede llamar a cualquiera de los métodos de ese objeto.

    Si quiere recuperar una instancia de clase WMI en otro espacio de nombres o en otro equipo, especifique el equipo y el espacio de nombres en el moniker. Para obtener más información, vea Creación de un script de WMI. Esto solo funciona si tiene los privilegios de acceso adecuados. Para obtener más información, vea Mantenimiento de la seguridad de WMI y Ejecución de operaciones con privilegios.

  2. Recupere todas las instancias individuales que quiera mediante los métodos de colección.

El ejemplo de código siguiente recupera un objeto SWbemServices y ejecuta el método InstancesOf para mostrar la propiedad size para todas las instancias de unidades lógicas en el equipo local.

Set objCol = GetObject("WinMgmts:").InstancesOf("Win32_LogicalDisk")
For Each Drive In objCol
    If Not IsNull(Drive.Size) Then    
       WScript.Echo ("Drive " & Drive.deviceid & " contains " & Drive.Size & " bytes")
    Else
       WScript.Echo ("Drive " & Drive.deviceid & " is not available.")
    End If
Next

Enumeración de WMI mediante C++

Además de realizar una enumeración básica, puede definir varias marcas y propiedades para aumentar el rendimiento de la enumeración. Para obtener más información, vea Mejora del rendimiento de la enumeración.

Procedimiento para enumerar un conjunto de objetos en WMI

  1. Cree una interfaz IEnumWbemClassObject que describa el conjunto de objetos que quiere enumerar.

    Un objeto IEnumWbemClassObject contiene una lista que describe un conjunto de objetos de WMI. Puede usar los métodos IEnumWbemClassObject para enumerar hacia adelante, omitir objetos, comenzar desde el principio y copiar el enumerador. En la tabla siguiente se enumeran los métodos que se usan para crear enumeradores para distintos tipos de objetos de WMI.

    Object Método
    Clase
    IWbemServices::CreateClassEnum
    [IWbemServices::CreateClassEnumAsync](/windows/desktop/api/WbemCli/nf-wbemcli-iwbemservices-createclassenumasync)
    Instancia
    IWbemServices::CreateInstanceEnum
    [IWbemServices::CreateInstanceEnumAsync](/windows/desktop/api/WbemCli/nf-wbemcli-iwbemservices-createinstanceenumasync)
    Resultado de la consulta
    IWbemServices::ExecQuery
    [IWbemServices::ExecQueryAsync](/windows/desktop/api/WbemCli/nf-wbemcli-iwbemservices-execqueryasync)
    Notificación de evento
    IWbemServices::ExecNotificationQuery
    [IWbemServices::ExecNotificationQueryAsync](/windows/desktop/api/WbemCli/nf-wbemcli-iwbemservices-execnotificationqueryasync)

     

  2. Recorra la enumeración devuelta mediante varias llamadas a IEnumWbemClassObject::Next o IEnumWbemClassObject::NextAsync.

Para obtener más información, vea Manipulación de la información de clases e instancias.